From 7295df4d6918a870b53df8e316b2df220010a216 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Tue, 18 Jun 2013 11:00:37 +0100 Subject: [PATCH] Bug 877762 - GC: Post-barrier cycle collector participants - 1 Fixes and updates to JS::Heap r=terrence --- js/public/RootingAPI.h | 29 ++++++++++------ js/public/Value.h | 76 +++++++++++++++++++++++++++++++++--------- 2 files changed, 79 insertions(+), 26 deletions(-) diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index 6ffe4597057f..49548452db76 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -181,18 +181,18 @@ class Heap : public js::HeapBase Heap() { MOZ_STATIC_ASSERT(sizeof(T) == sizeof(Heap), "Heap must be binary compatible with T."); - set(js::RootMethods::initial()); + init(js::RootMethods::initial()); } - explicit Heap(T p) { set(p); } - explicit Heap(const Heap &p) { set(p.ptr); } + explicit Heap(T p) { init(p); } + explicit Heap(const Heap &p) { init(p.ptr); } ~Heap() { if (js::RootMethods::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 } private: + void init(T newPtr) { + JS_ASSERT(!js::RootMethods::poisoned(newPtr)); + ptr = newPtr; + if (js::RootMethods::needsPostBarrier(ptr)) + post(); + } + void post() { #ifdef JSGC_GENERATIONAL JS_ASSERT(js::RootMethods::needsPostBarrier(ptr)); @@ -320,8 +327,8 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase 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 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 **thingGCRooters) { @@ -766,8 +773,8 @@ class FakeRooted : public RootedBase 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; diff --git a/js/public/Value.h b/js/public/Value.h index 610f99e87646..28556981bcc9 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -1420,6 +1420,7 @@ template <> struct RootMethods #endif }; +template class UnbarrieredMutableValueOperations; template class MutableValueOperations; /* @@ -1431,7 +1432,9 @@ template class MutableValueOperations; template class ValueOperations { + friend class UnbarrieredMutableValueOperations; friend class MutableValueOperations; + const JS::Value * value() const { return static_cast(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 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 with visible + * extractMutable() and extract() methods returning the const Value* and Value* + * abstracted by Outer. */ template -class MutableValueOperations : public ValueOperations +class UnbarrieredMutableValueOperations : public ValueOperations { + friend class MutableValueOperations; JS::Value * value() { return static_cast(this)->extractMutable(); } public: @@ -1484,26 +1489,65 @@ class MutableValueOperations : public ValueOperations 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 &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 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 with visible extractMutable() and extract() + * methods returning the const Value* and Value* abstracted by Outer. + */ +template +class MutableValueOperations : public UnbarrieredMutableValueOperations +{ + public: + void setString(JSString *str) { this->value()->setString(str); } + void setString(const JS::Anchor &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 interface when T = Value with + * type-querying, value-extracting, and mutating operations. */ template <> -class HeapBase : public ValueOperations > +class HeapBase : public UnbarrieredMutableValueOperations > { - friend class ValueOperations >; - const JS::Value * extract() const { - return static_cast*>(this)->address(); + typedef JS::Heap Outer; + + friend class ValueOperations; + friend class UnbarrieredMutableValueOperations; + + const JS::Value * extract() const { return static_cast(this)->address(); } + JS::Value * extractMutable() { return static_cast(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 *>(this)->set(v); + } + + public: + void setString(JSString *str) { setBarriered(JS::StringValue(str)); } + void setString(const JS::Anchor &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 : public MutableValueOperations*>(this)->address(); } + friend class UnbarrieredMutableValueOperations >; friend class MutableValueOperations >; JS::Value * extractMutable() { return static_cast*>(this)->address(); @@ -1550,6 +1595,7 @@ class RootedBase : public MutableValueOperations*>(this)->address(); } + friend class UnbarrieredMutableValueOperations >; friend class MutableValueOperations >; JS::Value * extractMutable() { return static_cast*>(this)->address();