mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 00:32:11 +00:00
Bug 744579 - Implement a relocatable version of HeapPtr; r=billm
We cannot store HeapPtrs in memory that may be realloced outside of the GC. Instead we should use the RelocatablePtr, which is more expensive, but is able to handle being moved, or EncapsulatedPtr which requires external barriers. --HG-- extra : rebase_source : 949c71cfdab8005339aea49437922f7f00a6f73a
This commit is contained in:
parent
cbefc3395f
commit
a3172ed2bc
@ -177,7 +177,7 @@ template <typename T, T v1, T v2> struct If<false, T, v1, v2> { static const T r
|
||||
/*
|
||||
* Traits class for identifying types that are implicitly barriered.
|
||||
*/
|
||||
template <class T> struct IsPostBarrieredType { static const bool result = false; };
|
||||
template <class T> struct IsRelocatableHeapType { static const bool result = true; };
|
||||
|
||||
} /* namespace tl */
|
||||
} /* namespace js */
|
||||
|
@ -213,7 +213,7 @@ struct VectorImpl<T, N, AP, true>
|
||||
template <class T, size_t N, class AllocPolicy>
|
||||
class Vector : private AllocPolicy
|
||||
{
|
||||
typedef typename tl::StaticAssert<!tl::IsPostBarrieredType<T>::result>::result _;
|
||||
typedef typename tl::StaticAssert<tl::IsRelocatableHeapType<T>::result>::result _;
|
||||
|
||||
/* utilities */
|
||||
|
||||
|
@ -151,31 +151,39 @@ struct JSXML;
|
||||
namespace js {
|
||||
|
||||
template<class T, typename Unioned = uintptr_t>
|
||||
class HeapPtr
|
||||
class EncapsulatedPtr
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
T *value;
|
||||
Unioned other;
|
||||
};
|
||||
|
||||
public:
|
||||
HeapPtr() : value(NULL) {}
|
||||
explicit HeapPtr(T *v) : value(v) { post(); }
|
||||
explicit HeapPtr(const HeapPtr<T> &v) : value(v.value) { post(); }
|
||||
EncapsulatedPtr() : value(NULL) {}
|
||||
explicit EncapsulatedPtr(T *v) : value(v) {}
|
||||
explicit EncapsulatedPtr(const EncapsulatedPtr<T> &v) : value(v.value) {}
|
||||
|
||||
~HeapPtr() { pre(); }
|
||||
|
||||
/* Use this to install a ptr into a newly allocated object. */
|
||||
void init(T *v) {
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||
value = v;
|
||||
post();
|
||||
}
|
||||
~EncapsulatedPtr() { pre(); }
|
||||
|
||||
/* Use to set the pointer to NULL. */
|
||||
void clear() {
|
||||
pre();
|
||||
value = NULL;
|
||||
pre();
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
EncapsulatedPtr<T, Unioned> &operator=(T *v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||
value = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
EncapsulatedPtr<T, Unioned> &operator=(const EncapsulatedPtr<T> &v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
|
||||
value = v.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Use this if the automatic coercion to T* isn't working. */
|
||||
@ -190,30 +198,48 @@ class HeapPtr
|
||||
|
||||
Unioned *unsafeGetUnioned() { return &other; }
|
||||
|
||||
HeapPtr<T, Unioned> &operator=(T *v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||
value = v;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
HeapPtr<T, Unioned> &operator=(const HeapPtr<T> &v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
|
||||
value = v.value;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator*() const { return *value; }
|
||||
T *operator->() const { return value; }
|
||||
|
||||
operator T*() const { return value; }
|
||||
|
||||
private:
|
||||
protected:
|
||||
void pre() { T::writeBarrierPre(value); }
|
||||
void post() { T::writeBarrierPost(value, (void *)&value); }
|
||||
};
|
||||
|
||||
template <class T, class Unioned = uintptr_t>
|
||||
class HeapPtr : public EncapsulatedPtr<T, Unioned>
|
||||
{
|
||||
public:
|
||||
HeapPtr() : EncapsulatedPtr<T>(NULL) {}
|
||||
explicit HeapPtr(T *v) : EncapsulatedPtr<T>(v) { post(); }
|
||||
explicit HeapPtr(const HeapPtr<T> &v)
|
||||
: EncapsulatedPtr<T>(v) { post(); }
|
||||
|
||||
void init(T *v) {
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||
this->value = v;
|
||||
post();
|
||||
}
|
||||
|
||||
HeapPtr<T, Unioned> &operator=(T *v) {
|
||||
this->pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||
this->value = v;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
HeapPtr<T, Unioned> &operator=(const HeapPtr<T> &v) {
|
||||
this->pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
|
||||
this->value = v.value;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
void post() { T::writeBarrierPost(this->value, (void *)&this->value); }
|
||||
|
||||
/* Make this friend so it can access pre() and post(). */
|
||||
template<class T1, class T2>
|
||||
@ -223,6 +249,41 @@ class HeapPtr
|
||||
HeapPtr<T2> &v2, T2 *val2);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class RelocatablePtr : public EncapsulatedPtr<T>
|
||||
{
|
||||
public:
|
||||
RelocatablePtr() : EncapsulatedPtr<T>(NULL) {}
|
||||
explicit RelocatablePtr(T *v) : EncapsulatedPtr<T>(v) { post(); }
|
||||
explicit RelocatablePtr(const RelocatablePtr<T> &v)
|
||||
: EncapsulatedPtr<T>(v) { post(); }
|
||||
|
||||
~RelocatablePtr() {
|
||||
this->pre();
|
||||
relocate();
|
||||
}
|
||||
|
||||
RelocatablePtr<T> &operator=(T *v) {
|
||||
this->pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||
this->value = v;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RelocatablePtr<T> &operator=(const RelocatablePtr<T> &v) {
|
||||
this->pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
|
||||
this->value = v.value;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
void post() { T::writeBarrierRelocPost(this->value, (void *)&this->value); }
|
||||
void relocate() { T::writeBarrierRelocated(this->value, (void *)&this->value); }
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a hack for RegExpStatics::updateFromMatch. It allows us to do two
|
||||
* barriers with only one branch to check if we're in an incremental GC.
|
||||
@ -247,6 +308,9 @@ struct Shape;
|
||||
class BaseShape;
|
||||
namespace types { struct TypeObject; }
|
||||
|
||||
typedef RelocatablePtr<JSObject> RelocatablePtrObject;
|
||||
typedef RelocatablePtr<JSScript> RelocatablePtrScript;
|
||||
|
||||
typedef HeapPtr<JSObject> HeapPtrObject;
|
||||
typedef HeapPtr<JSFunction> HeapPtrFunction;
|
||||
typedef HeapPtr<JSString> HeapPtrString;
|
||||
@ -269,7 +333,7 @@ struct HeapPtrHasher
|
||||
|
||||
/* Specialized hashing policy for HeapPtrs. */
|
||||
template <class T>
|
||||
struct DefaultHasher< HeapPtr<T> >: HeapPtrHasher<T> { };
|
||||
struct DefaultHasher< HeapPtr<T> > : HeapPtrHasher<T> { };
|
||||
|
||||
class EncapsulatedValue
|
||||
{
|
||||
@ -376,9 +440,6 @@ class RelocatableValue : public EncapsulatedValue
|
||||
inline RelocatableValue &operator=(const Value &v);
|
||||
inline RelocatableValue &operator=(const RelocatableValue &v);
|
||||
|
||||
static inline void writeBarrierPost(const Value &v, Value *addr);
|
||||
static inline void writeBarrierPost(JSCompartment *comp, const Value &v, Value *addr);
|
||||
|
||||
private:
|
||||
inline void post();
|
||||
inline void post(JSCompartment *comp);
|
||||
@ -421,7 +482,7 @@ class HeapSlot : public EncapsulatedValue
|
||||
* Run a post write barrier that encompasses multiple contiguous slots in a
|
||||
* single step.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
SlotRangeWriteBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t start, uint32_t count)
|
||||
{
|
||||
}
|
||||
@ -556,11 +617,11 @@ class ReadBarrieredValue
|
||||
|
||||
namespace tl {
|
||||
|
||||
template <class T> struct IsPostBarrieredType<HeapPtr<T> > {
|
||||
static const bool result = true; };
|
||||
template <> struct IsPostBarrieredType<HeapSlot> { static const bool result = true; };
|
||||
template <> struct IsPostBarrieredType<HeapValue> { static const bool result = true; };
|
||||
template <> struct IsPostBarrieredType<HeapId> { static const bool result = true; };
|
||||
template <class T> struct IsRelocatableHeapType<HeapPtr<T> >
|
||||
{ static const bool result = false; };
|
||||
template <> struct IsRelocatableHeapType<HeapSlot> { static const bool result = false; };
|
||||
template <> struct IsRelocatableHeapType<HeapValue> { static const bool result = false; };
|
||||
template <> struct IsRelocatableHeapType<HeapId> { static const bool result = false; };
|
||||
|
||||
} /* namespace tl */
|
||||
} /* namespace js */
|
||||
|
Loading…
Reference in New Issue
Block a user