Bug 877762 - GC: Post-barrier cycle collector participants - 1 Fixes and updates to JS::Heap<T> r=terrence

This commit is contained in:
Jon Coppeard 2013-06-18 11:00:37 +01:00
Родитель 115cb86ff1
Коммит 7295df4d69
2 изменённых файлов: 79 добавлений и 26 удалений

Просмотреть файл

@ -181,18 +181,18 @@ class Heap : public js::HeapBase<T>
Heap() {
MOZ_STATIC_ASSERT(sizeof(T) == sizeof(Heap<T>),
"Heap<T> must be binary compatible with T.");
set(js::RootMethods<T>::initial());
init(js::RootMethods<T>::initial());
}
explicit Heap(T p) { set(p); }
explicit Heap(const Heap<T> &p) { set(p.ptr); }
explicit Heap(T p) { init(p); }
explicit Heap(const Heap<T> &p) { init(p.ptr); }
~Heap() {
if (js::RootMethods<T>::needsPostBarrier(ptr))
relocate();
}
bool operator!=(const T &other) { return *ptr != other; }
bool operator==(const T &other) { return *ptr == other; }
bool operator!=(const T &other) const { return ptr != other; }
bool operator==(const T &other) const { return ptr == other; }
operator T() const { return ptr; }
T operator->() const { return ptr; }
@ -220,6 +220,13 @@ class Heap : public js::HeapBase<T>
}
private:
void init(T newPtr) {
JS_ASSERT(!js::RootMethods<T>::poisoned(newPtr));
ptr = newPtr;
if (js::RootMethods<T>::needsPostBarrier(ptr))
post();
}
void post() {
#ifdef JSGC_GENERATIONAL
JS_ASSERT(js::RootMethods<T>::needsPostBarrier(ptr));
@ -320,8 +327,8 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T>
operator const T&() const { return get(); }
T operator->() const { return get(); }
bool operator!=(const T &other) { return *ptr != other; }
bool operator==(const T &other) { return *ptr == other; }
bool operator!=(const T &other) const { return *ptr != other; }
bool operator==(const T &other) const { return *ptr == other; }
private:
Handle() {}
@ -605,8 +612,8 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
ptr = value;
}
bool operator!=(const T &other) { return ptr != other; }
bool operator==(const T &other) { return ptr == other; }
bool operator!=(const T &other) const { return ptr != other; }
bool operator==(const T &other) const { return ptr == other; }
private:
void commonInit(Rooted<void*> **thingGCRooters) {
@ -766,8 +773,8 @@ class FakeRooted : public RootedBase<T>
return ptr;
}
bool operator!=(const T &other) { return ptr != other; }
bool operator==(const T &other) { return ptr == other; }
bool operator!=(const T &other) const { return ptr != other; }
bool operator==(const T &other) const { return ptr == other; }
private:
T ptr;

Просмотреть файл

@ -1420,6 +1420,7 @@ template <> struct RootMethods<JS::Value>
#endif
};
template <class Outer> class UnbarrieredMutableValueOperations;
template <class Outer> class MutableValueOperations;
/*
@ -1431,7 +1432,9 @@ template <class Outer> class MutableValueOperations;
template <class Outer>
class ValueOperations
{
friend class UnbarrieredMutableValueOperations<Outer>;
friend class MutableValueOperations<Outer>;
const JS::Value * value() const { return static_cast<const Outer*>(this)->extract(); }
public:
@ -1469,14 +1472,16 @@ class ValueOperations
};
/*
* A class designed for CRTP use in implementing the mutating parts of the
* Value interface in Value-like classes. Outer must be a class inheriting
* MutableValueOperations<Outer> with visible extractMutable() and extract()
* methods returning the const Value* and Value* abstracted by Outer.
* A class designed for CRTP use in implementing the mutating parts of the Value
* interface in Value-like classes that don't need post barriers. Outer must be
* a class inheriting UnbarrieredMutableValueOperations<Outer> with visible
* extractMutable() and extract() methods returning the const Value* and Value*
* abstracted by Outer.
*/
template <class Outer>
class MutableValueOperations : public ValueOperations<Outer>
class UnbarrieredMutableValueOperations : public ValueOperations<Outer>
{
friend class MutableValueOperations<Outer>;
JS::Value * value() { return static_cast<Outer*>(this)->extractMutable(); }
public:
@ -1484,26 +1489,65 @@ class MutableValueOperations : public ValueOperations<Outer>
void setUndefined() { value()->setUndefined(); }
void setInt32(int32_t i) { value()->setInt32(i); }
void setDouble(double d) { value()->setDouble(d); }
void setString(JSString *str) { value()->setString(str); }
void setString(const JS::Anchor<JSString *> &str) { value()->setString(str); }
void setObject(JSObject &obj) { value()->setObject(obj); }
void setBoolean(bool b) { value()->setBoolean(b); }
void setMagic(JSWhyMagic why) { value()->setMagic(why); }
bool setNumber(uint32_t ui) { return value()->setNumber(ui); }
bool setNumber(double d) { return value()->setNumber(d); }
void setObjectOrNull(JSObject *arg) { value()->setObjectOrNull(arg); }
};
/*
* Augment the generic Heap<T> interface when T = Value with type-querying
* and value-extracting operations.
* A class designed for CRTP use in implementing all the mutating parts of the
* Value interface in Value-like classes. Outer must be a class inheriting
* MutableValueOperations<Outer> with visible extractMutable() and extract()
* methods returning the const Value* and Value* abstracted by Outer.
*/
template <class Outer>
class MutableValueOperations : public UnbarrieredMutableValueOperations<Outer>
{
public:
void setString(JSString *str) { this->value()->setString(str); }
void setString(const JS::Anchor<JSString *> &str) { this->value()->setString(str); }
void setObject(JSObject &obj) { this->value()->setObject(obj); }
void setObjectOrNull(JSObject *arg) { this->value()->setObjectOrNull(arg); }
};
/*
* Augment the generic Heap<T> interface when T = Value with
* type-querying, value-extracting, and mutating operations.
*/
template <>
class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
class HeapBase<JS::Value> : public UnbarrieredMutableValueOperations<JS::Heap<JS::Value> >
{
friend class ValueOperations<JS::Heap<JS::Value> >;
const JS::Value * extract() const {
return static_cast<const JS::Heap<JS::Value>*>(this)->address();
typedef JS::Heap<JS::Value> Outer;
friend class ValueOperations<Outer>;
friend class UnbarrieredMutableValueOperations<Outer>;
const JS::Value * extract() const { return static_cast<const Outer*>(this)->address(); }
JS::Value * extractMutable() { return static_cast<Outer*>(this)->unsafeGet(); }
/*
* Setters that potentially change the value to a GC thing from a non-GC
* thing must call JS::Heap::set() to trigger the post barrier.
*
* Changing from a GC thing to a non-GC thing value will leave the heap
* value in the store buffer, but it will be ingored so this is not a
* problem.
*/
void setBarriered(const JS::Value &v) {
static_cast<JS::Heap<JS::Value> *>(this)->set(v);
}
public:
void setString(JSString *str) { setBarriered(JS::StringValue(str)); }
void setString(const JS::Anchor<JSString *> &str) { setBarriered(JS::StringValue(str.get())); }
void setObject(JSObject &obj) { setBarriered(JS::ObjectValue(obj)); }
void setObjectOrNull(JSObject *arg) {
if (arg)
setObject(*arg);
else
setNull();
}
};
@ -1532,6 +1576,7 @@ class MutableHandleBase<JS::Value> : public MutableValueOperations<JS::MutableHa
return static_cast<const JS::MutableHandle<JS::Value>*>(this)->address();
}
friend class UnbarrieredMutableValueOperations<JS::MutableHandle<JS::Value> >;
friend class MutableValueOperations<JS::MutableHandle<JS::Value> >;
JS::Value * extractMutable() {
return static_cast<JS::MutableHandle<JS::Value>*>(this)->address();
@ -1550,6 +1595,7 @@ class RootedBase<JS::Value> : public MutableValueOperations<JS::Rooted<JS::Value
return static_cast<const JS::Rooted<JS::Value>*>(this)->address();
}
friend class UnbarrieredMutableValueOperations<JS::Rooted<JS::Value> >;
friend class MutableValueOperations<JS::Rooted<JS::Value> >;
JS::Value * extractMutable() {
return static_cast<JS::Rooted<JS::Value>*>(this)->address();