зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
7cc64cec66
Коммит
05a8238e35
|
@ -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);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче