Bug 915482 (part 1) - Move most of gc/Barrier-inl.h into gc/Barrier.h. r=terrence.

--HG--
extra : rebase_source : e3fbf54420858cd5ae5328f4cf5c5001d1d0ccb9
This commit is contained in:
Nicholas Nethercote 2013-09-11 16:51:17 -07:00
Родитель 7cc64cec66
Коммит 05a8238e35
4 изменённых файлов: 141 добавлений и 162 удалений

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

@ -22,6 +22,7 @@
#include "jstypes.h" #include "jstypes.h"
#include "js/RootingAPI.h"
#include "js/TypeDecls.h" #include "js/TypeDecls.h"
#include "js/Utility.h" #include "js/Utility.h"
@ -160,4 +161,30 @@ extern JS_PUBLIC_DATA(const jsid) JSID_EMPTY;
extern JS_PUBLIC_DATA(const JS::Handle<jsid>) JSID_VOIDHANDLE; extern JS_PUBLIC_DATA(const JS::Handle<jsid>) JSID_VOIDHANDLE;
extern JS_PUBLIC_DATA(const JS::Handle<jsid>) JSID_EMPTYHANDLE; extern JS_PUBLIC_DATA(const JS::Handle<jsid>) JSID_EMPTYHANDLE;
namespace js {
inline bool
IsPoisonedId(jsid iden)
{
if (JSID_IS_STRING(iden))
return JS::IsPoisonedPtr(JSID_TO_STRING(iden));
if (JSID_IS_OBJECT(iden))
return JS::IsPoisonedPtr(JSID_TO_OBJECT(iden));
return false;
}
template <> struct GCMethods<jsid>
{
static jsid initial() { return JSID_VOID; }
static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(jsid id) { return IsPoisonedId(id); }
static bool needsPostBarrier(jsid id) { return false; }
#ifdef JSGC_GENERATIONAL
static void postBarrier(jsid *idp) {}
static void relocate(jsid *idp) {}
#endif
};
}
#endif /* js_Id_h */ #endif /* js_Id_h */

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

@ -18,134 +18,6 @@
namespace js { namespace js {
/*
* This is a post barrier for HashTables whose key is a GC pointer. Any
* insertion into a HashTable not marked as part of the runtime, with a GC
* pointer as a key, must call this immediately after each insertion.
*/
template <class Map, class Key>
inline void
HashTableWriteBarrierPost(JSRuntime *rt, Map *map, const Key &key)
{
#ifdef JSGC_GENERATIONAL
if (key && IsInsideNursery(rt, key))
rt->gcStoreBuffer.putGeneric(gc::HashKeyRef<Map, Key>(map, key));
#endif
}
inline
EncapsulatedId::~EncapsulatedId()
{
pre();
}
inline EncapsulatedId &
EncapsulatedId::operator=(const EncapsulatedId &v)
{
if (v.value != value)
pre();
JS_ASSERT(!IsPoisonedId(v.value));
value = v.value;
return *this;
}
inline void
EncapsulatedId::pre()
{
#ifdef JSGC_INCREMENTAL
if (JSID_IS_OBJECT(value)) {
JSObject *obj = JSID_TO_OBJECT(value);
Zone *zone = obj->zone();
if (zone->needsBarrier()) {
js::gc::MarkObjectUnbarriered(zone->barrierTracer(), &obj, "write barrier");
JS_ASSERT(obj == JSID_TO_OBJECT(value));
}
} else if (JSID_IS_STRING(value)) {
JSString *str = JSID_TO_STRING(value);
Zone *zone = str->zone();
if (zone->needsBarrier()) {
js::gc::MarkStringUnbarriered(zone->barrierTracer(), &str, "write barrier");
JS_ASSERT(str == JSID_TO_STRING(value));
}
}
#endif
}
inline
RelocatableId::~RelocatableId()
{
pre();
}
inline RelocatableId &
RelocatableId::operator=(jsid id)
{
if (id != value)
pre();
JS_ASSERT(!IsPoisonedId(id));
value = id;
return *this;
}
inline RelocatableId &
RelocatableId::operator=(const RelocatableId &v)
{
if (v.value != value)
pre();
JS_ASSERT(!IsPoisonedId(v.value));
value = v.value;
return *this;
}
inline
HeapId::HeapId(jsid id)
: EncapsulatedId(id)
{
JS_ASSERT(!IsPoisonedId(id));
post();
}
inline
HeapId::~HeapId()
{
pre();
}
inline void
HeapId::init(jsid id)
{
JS_ASSERT(!IsPoisonedId(id));
value = id;
post();
}
inline void
HeapId::post()
{
}
inline HeapId &
HeapId::operator=(jsid id)
{
if (id != value)
pre();
JS_ASSERT(!IsPoisonedId(id));
value = id;
post();
return *this;
}
inline HeapId &
HeapId::operator=(const HeapId &v)
{
if (v.value != value)
pre();
JS_ASSERT(!IsPoisonedId(v.value));
value = v.value;
post();
return *this;
}
inline const Value & inline const Value &
ReadBarrieredValue::get() const ReadBarrieredValue::get() const
{ {

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

@ -124,11 +124,33 @@ namespace gc {
// Direct value access used by the write barriers and the jits. // Direct value access used by the write barriers and the jits.
void void
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name); MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
// These two declarations are also present in gc/Marking.h, via the DeclMarker
// macro. Not great, but hard to avoid.
void
MarkObjectUnbarriered(JSTracer *trc, JSObject **obj, const char *name);
void
MarkStringUnbarriered(JSTracer *trc, JSString **str, const char *name);
} }
// Note: these functions must be equivalent to the zone() functions implemented
// by all the subclasses of Cell.
JS::Zone * JS::Zone *
ZoneOfObject(const JSObject &obj); ZoneOfObject(const JSObject &obj);
static inline JS::shadow::Zone *
ShadowZoneOfObject(JSObject *obj)
{
return JS::shadow::Zone::asShadowZone(ZoneOfObject(*obj));
}
static inline JS::shadow::Zone *
ShadowZoneOfString(JSString *str)
{
return JS::shadow::Zone::asShadowZone(reinterpret_cast<const js::gc::Cell *>(str)->tenuredZone());
}
JS_ALWAYS_INLINE JS::Zone * JS_ALWAYS_INLINE JS::Zone *
ZoneOfValue(const JS::Value &value) ZoneOfValue(const JS::Value &value)
{ {
@ -138,6 +160,23 @@ ZoneOfValue(const JS::Value &value)
return static_cast<js::gc::Cell *>(value.toGCThing())->tenuredZone(); return static_cast<js::gc::Cell *>(value.toGCThing())->tenuredZone();
} }
/*
* This is a post barrier for HashTables whose key is a GC pointer. Any
* insertion into a HashTable not marked as part of the runtime, with a GC
* pointer as a key, must call this immediately after each insertion.
*/
template <class Map, class Key>
inline void
HashTableWriteBarrierPost(JSRuntime *rt, Map *map, const Key &key)
{
#ifdef JSGC_GENERATIONAL
if (key && IsInsideNursery(rt, key)) {
JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
shadowRuntime->gcStoreBufferPtr()->putGeneric(gc::HashKeyRef<Map, Key>(map, key));
}
#endif
}
template<class T, typename Unioned = uintptr_t> template<class T, typename Unioned = uintptr_t>
class EncapsulatedPtr class EncapsulatedPtr
{ {
@ -823,9 +862,15 @@ class EncapsulatedId
public: public:
explicit EncapsulatedId() : value(JSID_VOID) {} explicit EncapsulatedId() : value(JSID_VOID) {}
explicit EncapsulatedId(jsid id) : value(id) {} explicit EncapsulatedId(jsid id) : value(id) {}
~EncapsulatedId(); ~EncapsulatedId() { pre(); }
inline EncapsulatedId &operator=(const EncapsulatedId &v); EncapsulatedId &operator=(const EncapsulatedId &v) {
if (v.value != value)
pre();
JS_ASSERT(!IsPoisonedId(v.value));
value = v.value;
return *this;
}
bool operator==(jsid id) const { return value == id; } bool operator==(jsid id) const { return value == id; }
bool operator!=(jsid id) const { return value != id; } bool operator!=(jsid id) const { return value != id; }
@ -836,7 +881,25 @@ class EncapsulatedId
operator jsid() const { return value; } operator jsid() const { return value; }
protected: protected:
inline void pre(); void pre() {
#ifdef JSGC_INCREMENTAL
if (JSID_IS_OBJECT(value)) {
JSObject *obj = JSID_TO_OBJECT(value);
JS::shadow::Zone *shadowZone = ShadowZoneOfObject(obj);
if (shadowZone->needsBarrier()) {
js::gc::MarkObjectUnbarriered(shadowZone->barrierTracer(), &obj, "write barrier");
JS_ASSERT(obj == JSID_TO_OBJECT(value));
}
} else if (JSID_IS_STRING(value)) {
JSString *str = JSID_TO_STRING(value);
JS::shadow::Zone *shadowZone = ShadowZoneOfString(str);
if (shadowZone->needsBarrier()) {
js::gc::MarkStringUnbarriered(shadowZone->barrierTracer(), &str, "write barrier");
JS_ASSERT(str == JSID_TO_STRING(value));
}
}
#endif
}
}; };
class RelocatableId : public EncapsulatedId class RelocatableId : public EncapsulatedId
@ -844,26 +907,65 @@ class RelocatableId : public EncapsulatedId
public: public:
explicit RelocatableId() : EncapsulatedId() {} explicit RelocatableId() : EncapsulatedId() {}
explicit inline RelocatableId(jsid id) : EncapsulatedId(id) {} explicit inline RelocatableId(jsid id) : EncapsulatedId(id) {}
inline ~RelocatableId(); ~RelocatableId() { pre(); }
inline RelocatableId &operator=(jsid id); RelocatableId &operator=(jsid id) {
inline RelocatableId &operator=(const RelocatableId &v); if (id != value)
pre();
JS_ASSERT(!IsPoisonedId(id));
value = id;
return *this;
}
RelocatableId &operator=(const RelocatableId &v) {
if (v.value != value)
pre();
JS_ASSERT(!IsPoisonedId(v.value));
value = v.value;
return *this;
}
}; };
class HeapId : public EncapsulatedId class HeapId : public EncapsulatedId
{ {
public: public:
explicit HeapId() : EncapsulatedId() {} explicit HeapId() : EncapsulatedId() {}
explicit inline HeapId(jsid id);
inline ~HeapId();
inline void init(jsid id); explicit HeapId(jsid id)
: EncapsulatedId(id)
{
JS_ASSERT(!IsPoisonedId(id));
post();
}
inline HeapId &operator=(jsid id); ~HeapId() { pre(); }
inline HeapId &operator=(const HeapId &v);
void init(jsid id) {
JS_ASSERT(!IsPoisonedId(id));
value = id;
post();
}
HeapId &operator=(jsid id) {
if (id != value)
pre();
JS_ASSERT(!IsPoisonedId(id));
value = id;
post();
return *this;
}
HeapId &operator=(const HeapId &v) {
if (v.value != value)
pre();
JS_ASSERT(!IsPoisonedId(v.value));
value = v.value;
post();
return *this;
}
private: private:
inline void post(); void post() {};
HeapId(const HeapId &v) MOZ_DELETE; HeapId(const HeapId &v) MOZ_DELETE;
}; };

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

@ -1359,28 +1359,6 @@ JS_IsInRequest(JSRuntime *rt);
namespace js { namespace js {
inline bool
IsPoisonedId(jsid iden)
{
if (JSID_IS_STRING(iden))
return JS::IsPoisonedPtr(JSID_TO_STRING(iden));
if (JSID_IS_OBJECT(iden))
return JS::IsPoisonedPtr(JSID_TO_OBJECT(iden));
return false;
}
template <> struct GCMethods<jsid>
{
static jsid initial() { return JSID_VOID; }
static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(jsid id) { return IsPoisonedId(id); }
static bool needsPostBarrier(jsid id) { return false; }
#ifdef JSGC_GENERATIONAL
static void postBarrier(jsid *idp) {}
static void relocate(jsid *idp) {}
#endif
};
void void
AssertHeapIsIdle(JSRuntime *rt); AssertHeapIsIdle(JSRuntime *rt);