зеркало из https://github.com/mozilla/gecko-dev.git
Bug 910771 (part 4) - Move all the methods of EncapsulatedValue, HeapValue, RelocatableValue, and HeapSlot from gc/Barrier-inl.h to gc/Barrier.h. r=terrence.
This commit is contained in:
Родитель
519a3c2851
Коммит
9339a831e1
|
@ -18,15 +18,6 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
JS_ALWAYS_INLINE JS::Zone *
|
||||
ZoneOfValue(const JS::Value &value)
|
||||
{
|
||||
JS_ASSERT(value.isMarkable());
|
||||
if (value.isObject())
|
||||
return value.toObject().zone();
|
||||
return static_cast<js::gc::Cell *>(value.toGCThing())->tenuredZone();
|
||||
}
|
||||
|
||||
template <typename T, typename Unioned>
|
||||
void
|
||||
EncapsulatedPtr<T, Unioned>::pre()
|
||||
|
@ -53,353 +44,6 @@ RelocatablePtr<T>::relocate(JSRuntime *rt)
|
|||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
EncapsulatedValue::~EncapsulatedValue()
|
||||
{
|
||||
pre();
|
||||
}
|
||||
|
||||
inline EncapsulatedValue &
|
||||
EncapsulatedValue::operator=(const Value &v)
|
||||
{
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline EncapsulatedValue &
|
||||
EncapsulatedValue::operator=(const EncapsulatedValue &v)
|
||||
{
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v.get();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void
|
||||
EncapsulatedValue::writeBarrierPre(const Value &value)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (value.isMarkable() && runtimeFromAnyThread(value)->needsBarrier())
|
||||
writeBarrierPre(ZoneOfValue(value), value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
EncapsulatedValue::writeBarrierPre(Zone *zone, const Value &value)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (zone->needsBarrier()) {
|
||||
JS_ASSERT_IF(value.isMarkable(), runtimeFromMainThread(value)->needsBarrier());
|
||||
Value tmp(value);
|
||||
js::gc::MarkValueUnbarriered(zone->barrierTracer(), &tmp, "write barrier");
|
||||
JS_ASSERT(tmp == value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
EncapsulatedValue::pre()
|
||||
{
|
||||
writeBarrierPre(value);
|
||||
}
|
||||
|
||||
inline void
|
||||
EncapsulatedValue::pre(Zone *zone)
|
||||
{
|
||||
writeBarrierPre(zone, value);
|
||||
}
|
||||
|
||||
inline
|
||||
HeapValue::HeapValue()
|
||||
: EncapsulatedValue(UndefinedValue())
|
||||
{
|
||||
post();
|
||||
}
|
||||
|
||||
inline
|
||||
HeapValue::HeapValue(const Value &v)
|
||||
: EncapsulatedValue(v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
post();
|
||||
}
|
||||
|
||||
inline
|
||||
HeapValue::HeapValue(const HeapValue &v)
|
||||
: EncapsulatedValue(v.value)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v.value));
|
||||
post();
|
||||
}
|
||||
|
||||
inline
|
||||
HeapValue::~HeapValue()
|
||||
{
|
||||
pre();
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::init(const Value &v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post();
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::init(JSRuntime *rt, const Value &v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(rt);
|
||||
}
|
||||
|
||||
inline HeapValue &
|
||||
HeapValue::operator=(const Value &v)
|
||||
{
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline HeapValue &
|
||||
HeapValue::operator=(const HeapValue &v)
|
||||
{
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v.value));
|
||||
value = v.value;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::set(Zone *zone, const Value &v)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (value.isMarkable()) {
|
||||
JS_ASSERT(ZoneOfValue(value) == zone ||
|
||||
zone->runtimeFromAnyThread()->isAtomsZone(ZoneOfValue(value)));
|
||||
}
|
||||
#endif
|
||||
|
||||
pre(zone);
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(zone->runtimeFromAnyThread());
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPost(const Value &value, Value *addr)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (value.isMarkable())
|
||||
runtimeFromMainThread(value)->gcStoreBuffer.putValue(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPost(JSRuntime *rt, const Value &value, Value *addr)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (value.isMarkable())
|
||||
rt->gcStoreBuffer.putValue(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::post()
|
||||
{
|
||||
writeBarrierPost(value, &value);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::post(JSRuntime *rt)
|
||||
{
|
||||
writeBarrierPost(rt, value, &value);
|
||||
}
|
||||
|
||||
inline
|
||||
RelocatableValue::RelocatableValue()
|
||||
: EncapsulatedValue(UndefinedValue())
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
RelocatableValue::RelocatableValue(const Value &v)
|
||||
: EncapsulatedValue(v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
if (v.isMarkable())
|
||||
post();
|
||||
}
|
||||
|
||||
inline
|
||||
RelocatableValue::RelocatableValue(const RelocatableValue &v)
|
||||
: EncapsulatedValue(v.value)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v.value));
|
||||
if (v.value.isMarkable())
|
||||
post();
|
||||
}
|
||||
|
||||
inline
|
||||
RelocatableValue::~RelocatableValue()
|
||||
{
|
||||
if (value.isMarkable())
|
||||
relocate(runtimeFromMainThread(value));
|
||||
}
|
||||
|
||||
inline RelocatableValue &
|
||||
RelocatableValue::operator=(const Value &v)
|
||||
{
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
if (v.isMarkable()) {
|
||||
value = v;
|
||||
post();
|
||||
} else if (value.isMarkable()) {
|
||||
JSRuntime *rt = runtimeFromMainThread(value);
|
||||
relocate(rt);
|
||||
value = v;
|
||||
} else {
|
||||
value = v;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline RelocatableValue &
|
||||
RelocatableValue::operator=(const RelocatableValue &v)
|
||||
{
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v.value));
|
||||
if (v.value.isMarkable()) {
|
||||
value = v.value;
|
||||
post();
|
||||
} else if (value.isMarkable()) {
|
||||
JSRuntime *rt = runtimeFromMainThread(value);
|
||||
relocate(rt);
|
||||
value = v.value;
|
||||
} else {
|
||||
value = v.value;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void
|
||||
RelocatableValue::post()
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS_ASSERT(value.isMarkable());
|
||||
runtimeFromMainThread(value)->gcStoreBuffer.putRelocatableValue(&value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
RelocatableValue::relocate(JSRuntime *rt)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
rt->gcStoreBuffer.removeRelocatableValue(&value);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
HeapSlot::HeapSlot(JSObject *obj, Kind kind, uint32_t slot, const Value &v)
|
||||
: EncapsulatedValue(v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
post(obj, kind, slot, v);
|
||||
}
|
||||
|
||||
inline
|
||||
HeapSlot::HeapSlot(JSObject *obj, Kind kind, uint32_t slot, const HeapSlot &s)
|
||||
: EncapsulatedValue(s.value)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(s.value));
|
||||
post(obj, kind, slot, s);
|
||||
}
|
||||
|
||||
inline
|
||||
HeapSlot::~HeapSlot()
|
||||
{
|
||||
pre();
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::init(JSObject *obj, Kind kind, uint32_t slot, const Value &v)
|
||||
{
|
||||
value = v;
|
||||
post(obj, kind, slot, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::init(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot, const Value &v)
|
||||
{
|
||||
value = v;
|
||||
post(rt, obj, kind, slot, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::set(JSObject *obj, Kind kind, uint32_t slot, const Value &v)
|
||||
{
|
||||
JS_ASSERT_IF(kind == Slot, &obj->getSlotRef(slot) == this);
|
||||
JS_ASSERT_IF(kind == Element, &obj->getDenseElement(slot) == (const Value *)this);
|
||||
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(obj, kind, slot, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::set(Zone *zone, JSObject *obj, Kind kind, uint32_t slot, const Value &v)
|
||||
{
|
||||
JS_ASSERT_IF(kind == Slot, &obj->getSlotRef(slot) == this);
|
||||
JS_ASSERT_IF(kind == Element, &obj->getDenseElement(slot) == (const Value *)this);
|
||||
JS_ASSERT(obj->zone() == zone);
|
||||
|
||||
pre(zone);
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(zone->runtimeFromAnyThread(), obj, kind, slot, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::writeBarrierPost(JSObject *obj, Kind kind, uint32_t slot, Value target)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
writeBarrierPost(obj->runtimeFromAnyThread(), obj, kind, slot, target);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::writeBarrierPost(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot, Value target)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS_ASSERT_IF(kind == Slot, obj->getSlotAddressUnchecked(slot)->get() == target);
|
||||
JS_ASSERT_IF(kind == Element,
|
||||
static_cast<HeapSlot *>(obj->getDenseElements() + slot)->get() == target);
|
||||
|
||||
if (target.isObject())
|
||||
rt->gcStoreBuffer.putSlot(obj, kind, slot, &target.toObject());
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::post(JSObject *owner, Kind kind, uint32_t slot, Value target)
|
||||
{
|
||||
HeapSlot::writeBarrierPost(owner, kind, slot, target);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::post(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot, Value target)
|
||||
{
|
||||
HeapSlot::writeBarrierPost(rt, owner, kind, slot, target);
|
||||
}
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
class DenseRangeRef : public gc::BufferableRef
|
||||
{
|
||||
|
@ -449,7 +93,6 @@ HashTableWriteBarrierPost(JSRuntime *rt, Map *map, const Key &key)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
EncapsulatedId::~EncapsulatedId()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "vm/ObjectImpl-inl.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
bool
|
||||
HeapValue::preconditionForSet(Zone *zone)
|
||||
{
|
||||
if (!value.isMarkable())
|
||||
return true;
|
||||
|
||||
return ZoneOfValue(value) == zone ||
|
||||
zone->runtimeFromAnyThread()->isAtomsZone(ZoneOfValue(value));
|
||||
}
|
||||
|
||||
bool
|
||||
HeapSlot::preconditionForSet(JSObject *owner, Kind kind, uint32_t slot)
|
||||
{
|
||||
return kind == Slot
|
||||
? &owner->getSlotRef(slot) == this
|
||||
: &owner->getDenseElement(slot) == (const Value *)this;
|
||||
}
|
||||
|
||||
bool
|
||||
HeapSlot::preconditionForSet(Zone *zone, JSObject *owner, Kind kind, uint32_t slot)
|
||||
{
|
||||
bool ok = kind == Slot
|
||||
? &owner->getSlotRef(slot) == this
|
||||
: &owner->getDenseElement(slot) == (const Value *)this;
|
||||
return ok && owner->zone() == zone;
|
||||
}
|
||||
|
||||
void
|
||||
HeapSlot::preconditionForWriteBarrierPost(JSObject *obj, Kind kind, uint32_t slot, Value target)
|
||||
{
|
||||
JS_ASSERT_IF(kind == Slot, obj->getSlotAddressUnchecked(slot)->get() == target);
|
||||
JS_ASSERT_IF(kind == Element,
|
||||
static_cast<HeapSlot *>(obj->getDenseElements() + slot)->get() == target);
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
} // namespace js
|
|
@ -120,6 +120,24 @@ namespace js {
|
|||
|
||||
class PropertyName;
|
||||
|
||||
namespace gc {
|
||||
// Direct value access used by the write barriers and the jits.
|
||||
void
|
||||
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
|
||||
}
|
||||
|
||||
JS::Zone *
|
||||
ZoneOfObject(const JSObject &obj);
|
||||
|
||||
JS_ALWAYS_INLINE JS::Zone *
|
||||
ZoneOfValue(const JS::Value &value)
|
||||
{
|
||||
JS_ASSERT(value.isMarkable());
|
||||
if (value.isObject())
|
||||
return ZoneOfObject(value.toObject());
|
||||
return static_cast<js::gc::Cell *>(value.toGCThing())->tenuredZone();
|
||||
}
|
||||
|
||||
template<class T, typename Unioned = uintptr_t>
|
||||
class EncapsulatedPtr
|
||||
{
|
||||
|
@ -393,7 +411,10 @@ class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
|
|||
EncapsulatedValue(const EncapsulatedValue &v) : value(v) {
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
}
|
||||
inline ~EncapsulatedValue();
|
||||
|
||||
~EncapsulatedValue() {
|
||||
pre();
|
||||
}
|
||||
|
||||
void init(const Value &v) {
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
|
@ -404,8 +425,19 @@ class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
|
|||
value = v;
|
||||
}
|
||||
|
||||
inline EncapsulatedValue &operator=(const Value &v);
|
||||
inline EncapsulatedValue &operator=(const EncapsulatedValue &v);
|
||||
EncapsulatedValue &operator=(const Value &v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
EncapsulatedValue &operator=(const EncapsulatedValue &v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v.get();
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const EncapsulatedValue &v) const { return value == v.value; }
|
||||
bool operator!=(const EncapsulatedValue &v) const { return value != v.value; }
|
||||
|
@ -418,12 +450,28 @@ class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
|
|||
|
||||
uint64_t asRawBits() const { return value.asRawBits(); }
|
||||
|
||||
static inline void writeBarrierPre(const Value &v);
|
||||
static inline void writeBarrierPre(Zone *zone, const Value &v);
|
||||
static void writeBarrierPre(const Value &v) {
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (v.isMarkable() && shadowRuntimeFromAnyThread(v)->needsBarrier())
|
||||
writeBarrierPre(ZoneOfValue(v), v);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void writeBarrierPre(Zone *zone, const Value &v) {
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
JS::shadow::Zone *shadowZone = JS::shadow::Zone::asShadowZone(zone);
|
||||
if (shadowZone->needsBarrier()) {
|
||||
JS_ASSERT_IF(v.isMarkable(), shadowRuntimeFromMainThread(v)->needsBarrier());
|
||||
Value tmp(v);
|
||||
js::gc::MarkValueUnbarriered(shadowZone->barrierTracer(), &tmp, "write barrier");
|
||||
JS_ASSERT(tmp == v);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
inline void pre();
|
||||
inline void pre(Zone *zone);
|
||||
void pre() { writeBarrierPre(value); }
|
||||
void pre(Zone *zone) { writeBarrierPre(zone, value); }
|
||||
|
||||
static JSRuntime *runtimeFromMainThread(const Value &v) {
|
||||
JS_ASSERT(v.isMarkable());
|
||||
|
@ -448,16 +496,61 @@ class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
|
|||
class HeapValue : public EncapsulatedValue
|
||||
{
|
||||
public:
|
||||
explicit inline HeapValue();
|
||||
explicit inline HeapValue(const Value &v);
|
||||
explicit inline HeapValue(const HeapValue &v);
|
||||
inline ~HeapValue();
|
||||
explicit HeapValue()
|
||||
: EncapsulatedValue(UndefinedValue())
|
||||
{
|
||||
post();
|
||||
}
|
||||
|
||||
inline void init(const Value &v);
|
||||
inline void init(JSRuntime *rt, const Value &v);
|
||||
explicit HeapValue(const Value &v)
|
||||
: EncapsulatedValue(v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
post();
|
||||
}
|
||||
|
||||
inline HeapValue &operator=(const Value &v);
|
||||
inline HeapValue &operator=(const HeapValue &v);
|
||||
explicit HeapValue(const HeapValue &v)
|
||||
: EncapsulatedValue(v.value)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v.value));
|
||||
post();
|
||||
}
|
||||
|
||||
~HeapValue() {
|
||||
pre();
|
||||
}
|
||||
|
||||
void init(const Value &v) {
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post();
|
||||
}
|
||||
|
||||
void init(JSRuntime *rt, const Value &v) {
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(rt);
|
||||
}
|
||||
|
||||
HeapValue &operator=(const Value &v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
HeapValue &operator=(const HeapValue &v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v.value));
|
||||
value = v.value;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool preconditionForSet(Zone *zone);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is a faster version of operator=. Normally, operator= has to
|
||||
|
@ -465,30 +558,116 @@ class HeapValue : public EncapsulatedValue
|
|||
* the barrier. If you already know the compartment, it's faster to pass it
|
||||
* in.
|
||||
*/
|
||||
inline void set(Zone *zone, const Value &v);
|
||||
void set(Zone *zone, const Value &v) {
|
||||
JS::shadow::Zone *shadowZone = JS::shadow::Zone::asShadowZone(zone);
|
||||
JS_ASSERT(preconditionForSet(zone));
|
||||
pre(zone);
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(shadowZone->runtimeFromAnyThread());
|
||||
}
|
||||
|
||||
static inline void writeBarrierPost(const Value &v, Value *addr);
|
||||
static inline void writeBarrierPost(JSRuntime *rt, const Value &v, Value *addr);
|
||||
static void writeBarrierPost(const Value &value, Value *addr) {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (value.isMarkable())
|
||||
shadowRuntimeFromMainThread(value)->gcStoreBufferPtr()->putValue(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void writeBarrierPost(JSRuntime *rt, const Value &value, Value *addr) {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (value.isMarkable()) {
|
||||
JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
|
||||
shadowRuntime->gcStoreBufferPtr()->putValue(addr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
inline void post();
|
||||
inline void post(JSRuntime *rt);
|
||||
void post() {
|
||||
writeBarrierPost(value, &value);
|
||||
}
|
||||
|
||||
void post(JSRuntime *rt) {
|
||||
writeBarrierPost(rt, value, &value);
|
||||
}
|
||||
};
|
||||
|
||||
class RelocatableValue : public EncapsulatedValue
|
||||
{
|
||||
public:
|
||||
explicit inline RelocatableValue();
|
||||
explicit inline RelocatableValue(const Value &v);
|
||||
inline RelocatableValue(const RelocatableValue &v);
|
||||
inline ~RelocatableValue();
|
||||
explicit RelocatableValue()
|
||||
: EncapsulatedValue(UndefinedValue())
|
||||
{}
|
||||
|
||||
inline RelocatableValue &operator=(const Value &v);
|
||||
inline RelocatableValue &operator=(const RelocatableValue &v);
|
||||
explicit RelocatableValue(const Value &v)
|
||||
: EncapsulatedValue(v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
if (v.isMarkable())
|
||||
post();
|
||||
}
|
||||
|
||||
RelocatableValue(const RelocatableValue &v)
|
||||
: EncapsulatedValue(v.value)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v.value));
|
||||
if (v.value.isMarkable())
|
||||
post();
|
||||
}
|
||||
|
||||
~RelocatableValue()
|
||||
{
|
||||
if (value.isMarkable())
|
||||
relocate(runtimeFromMainThread(value));
|
||||
}
|
||||
|
||||
RelocatableValue &operator=(const Value &v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
if (v.isMarkable()) {
|
||||
value = v;
|
||||
post();
|
||||
} else if (value.isMarkable()) {
|
||||
JSRuntime *rt = runtimeFromMainThread(value);
|
||||
relocate(rt);
|
||||
value = v;
|
||||
} else {
|
||||
value = v;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RelocatableValue &operator=(const RelocatableValue &v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v.value));
|
||||
if (v.value.isMarkable()) {
|
||||
value = v.value;
|
||||
post();
|
||||
} else if (value.isMarkable()) {
|
||||
JSRuntime *rt = runtimeFromMainThread(value);
|
||||
relocate(rt);
|
||||
value = v.value;
|
||||
} else {
|
||||
value = v.value;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
inline void post();
|
||||
inline void relocate(JSRuntime *rt);
|
||||
void post() {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS_ASSERT(value.isMarkable());
|
||||
shadowRuntimeFromMainThread(value)->gcStoreBufferPtr()->putRelocatableValue(&value);
|
||||
#endif
|
||||
}
|
||||
|
||||
void relocate(JSRuntime *rt) {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
|
||||
shadowRuntime->gcStoreBufferPtr()->removeRelocatableValue(&value);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
class HeapSlot : public EncapsulatedValue
|
||||
|
@ -507,24 +686,90 @@ class HeapSlot : public EncapsulatedValue
|
|||
Element
|
||||
};
|
||||
|
||||
explicit inline HeapSlot() MOZ_DELETE;
|
||||
explicit inline HeapSlot(JSObject *obj, Kind kind, uint32_t slot, const Value &v);
|
||||
explicit inline HeapSlot(JSObject *obj, Kind kind, uint32_t slot, const HeapSlot &v);
|
||||
inline ~HeapSlot();
|
||||
explicit HeapSlot() MOZ_DELETE;
|
||||
|
||||
inline void init(JSObject *owner, Kind kind, uint32_t slot, const Value &v);
|
||||
inline void init(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot, const Value &v);
|
||||
explicit HeapSlot(JSObject *obj, Kind kind, uint32_t slot, const Value &v)
|
||||
: EncapsulatedValue(v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
post(obj, kind, slot, v);
|
||||
}
|
||||
|
||||
inline void set(JSObject *owner, Kind kind, uint32_t slot, const Value &v);
|
||||
inline void set(Zone *zone, JSObject *owner, Kind kind, uint32_t slot, const Value &v);
|
||||
explicit HeapSlot(JSObject *obj, Kind kind, uint32_t slot, const HeapSlot &s)
|
||||
: EncapsulatedValue(s.value)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(s.value));
|
||||
post(obj, kind, slot, s);
|
||||
}
|
||||
|
||||
static inline void writeBarrierPost(JSObject *obj, Kind kind, uint32_t slot, Value target);
|
||||
static inline void writeBarrierPost(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot,
|
||||
Value target);
|
||||
~HeapSlot() {
|
||||
pre();
|
||||
}
|
||||
|
||||
void init(JSObject *owner, Kind kind, uint32_t slot, const Value &v) {
|
||||
value = v;
|
||||
post(owner, kind, slot, v);
|
||||
}
|
||||
|
||||
void init(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot, const Value &v) {
|
||||
value = v;
|
||||
post(rt, owner, kind, slot, v);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool preconditionForSet(JSObject *owner, Kind kind, uint32_t slot);
|
||||
bool preconditionForSet(Zone *zone, JSObject *owner, Kind kind, uint32_t slot);
|
||||
static void preconditionForWriteBarrierPost(JSObject *obj, Kind kind, uint32_t slot,
|
||||
Value target);
|
||||
#endif
|
||||
|
||||
void set(JSObject *owner, Kind kind, uint32_t slot, const Value &v) {
|
||||
JS_ASSERT(preconditionForSet(owner, kind, slot));
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(owner, kind, slot, v);
|
||||
}
|
||||
|
||||
void set(Zone *zone, JSObject *owner, Kind kind, uint32_t slot, const Value &v) {
|
||||
JS_ASSERT(preconditionForSet(zone, owner, kind, slot));
|
||||
JS::shadow::Zone *shadowZone = JS::shadow::Zone::asShadowZone(zone);
|
||||
pre(zone);
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(shadowZone->runtimeFromAnyThread(), owner, kind, slot, v);
|
||||
}
|
||||
|
||||
static void writeBarrierPost(JSObject *obj, Kind kind, uint32_t slot, Value target)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
js::gc::Cell *cell = reinterpret_cast<js::gc::Cell*>(obj);
|
||||
writeBarrierPost(cell->runtimeFromAnyThread(), obj, kind, slot, target);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void writeBarrierPost(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot,
|
||||
Value target)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
preconditionForWriteBarrierPost(obj, kind, slot, target);
|
||||
#endif
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (target.isObject()) {
|
||||
JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
|
||||
shadowRuntime->gcStoreBufferPtr()->putSlot(obj, kind, slot, &target.toObject());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
inline void post(JSObject *owner, Kind kind, uint32_t slot, Value target);
|
||||
inline void post(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot, Value target);
|
||||
void post(JSObject *owner, Kind kind, uint32_t slot, Value target) {
|
||||
HeapSlot::writeBarrierPost(owner, kind, slot, target);
|
||||
}
|
||||
|
||||
void post(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot, Value target) {
|
||||
HeapSlot::writeBarrierPost(rt, owner, kind, slot, target);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -223,10 +223,6 @@ MarkCrossCompartmentSlot(JSTracer *trc, JSObject *src, HeapSlot *dst_slot, const
|
|||
void
|
||||
MarkObject(JSTracer *trc, HeapPtr<GlobalObject, JSScript *> *thingp, const char *name);
|
||||
|
||||
/* Direct value access used by the write barriers and the methodjit. */
|
||||
void
|
||||
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
|
||||
|
||||
/*
|
||||
* MarkChildren<JSObject> is exposed solely for preWriteBarrier on
|
||||
* JSObject::TradeGuts. It should not be considered external interface.
|
||||
|
|
|
@ -234,3 +234,11 @@ Zone::discardJitCode(FreeOp *fop, bool discardConstraints)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
JS::Zone *
|
||||
js::ZoneOfObject(const JSObject &obj)
|
||||
{
|
||||
return obj.zone();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ EXPORTS.js += [
|
|||
|
||||
CPP_SOURCES += [
|
||||
'ArgumentsObject.cpp',
|
||||
'TypedObject.cpp',
|
||||
'Barrier.cpp',
|
||||
'BytecodeCompiler.cpp',
|
||||
'BytecodeEmitter.cpp',
|
||||
'CallNonGenericMethod.cpp',
|
||||
|
@ -136,6 +136,7 @@ CPP_SOURCES += [
|
|||
'Tracer.cpp',
|
||||
'TypeRepresentation.cpp',
|
||||
'TypedArrayObject.cpp',
|
||||
'TypedObject.cpp',
|
||||
'Unicode.cpp',
|
||||
'Value.cpp',
|
||||
'Verifier.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче