This commit is contained in:
Terrence Cole 2014-07-28 10:16:56 -07:00
Родитель 9bc76bfb73
Коммит 68b8d91b1f
16 изменённых файлов: 148 добавлений и 78 удалений

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

@ -151,12 +151,40 @@
*/ */
class JSAtom; class JSAtom;
struct JSCompartment;
class JSFlatString; class JSFlatString;
class JSLinearString; class JSLinearString;
namespace JS {
class Symbol;
}
namespace js { namespace js {
class ArgumentsObject;
class ArrayBufferObject;
class ArrayBufferViewObject;
class SharedArrayBufferObject;
class BaseShape;
class DebugScopeObject;
class GlobalObject;
class LazyScript;
class Nursery;
class ObjectImpl;
class PropertyName; class PropertyName;
class SavedFrame;
class ScopeObject;
class ScriptSourceObject;
class Shape;
class UnownedBaseShape;
namespace types {
struct TypeObject;
}
namespace jit {
class JitCode;
}
#ifdef DEBUG #ifdef DEBUG
bool bool
@ -173,6 +201,32 @@ StringIsPermanentAtom(JSString *str);
namespace gc { namespace gc {
template <typename T> struct MapTypeToTraceKind {};
template <> struct MapTypeToTraceKind<ArgumentsObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<ArrayBufferObject>{ static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<ArrayBufferViewObject>{ static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<BaseShape> { static const JSGCTraceKind kind = JSTRACE_BASE_SHAPE; };
template <> struct MapTypeToTraceKind<DebugScopeObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<GlobalObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<JS::Symbol> { static const JSGCTraceKind kind = JSTRACE_SYMBOL; };
template <> struct MapTypeToTraceKind<JSAtom> { static const JSGCTraceKind kind = JSTRACE_STRING; };
template <> struct MapTypeToTraceKind<JSFlatString> { static const JSGCTraceKind kind = JSTRACE_STRING; };
template <> struct MapTypeToTraceKind<JSFunction> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<JSLinearString> { static const JSGCTraceKind kind = JSTRACE_STRING; };
template <> struct MapTypeToTraceKind<JSObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<JSScript> { static const JSGCTraceKind kind = JSTRACE_SCRIPT; };
template <> struct MapTypeToTraceKind<JSString> { static const JSGCTraceKind kind = JSTRACE_STRING; };
template <> struct MapTypeToTraceKind<LazyScript> { static const JSGCTraceKind kind = JSTRACE_LAZY_SCRIPT; };
template <> struct MapTypeToTraceKind<ObjectImpl> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<PropertyName> { static const JSGCTraceKind kind = JSTRACE_STRING; };
template <> struct MapTypeToTraceKind<SavedFrame> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<ScopeObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<Shape> { static const JSGCTraceKind kind = JSTRACE_SHAPE; };
template <> struct MapTypeToTraceKind<SharedArrayBufferObject>{ static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<UnownedBaseShape> { static const JSGCTraceKind kind = JSTRACE_BASE_SHAPE; };
template <> struct MapTypeToTraceKind<jit::JitCode> { static const JSGCTraceKind kind = JSTRACE_JITCODE; };
template <> struct MapTypeToTraceKind<types::TypeObject>{ static const JSGCTraceKind kind = JSTRACE_TYPE_OBJECT; };
template <typename T> template <typename T>
void void
MarkUnbarriered(JSTracer *trc, T **thingp, const char *name); MarkUnbarriered(JSTracer *trc, T **thingp, const char *name);
@ -206,6 +260,7 @@ class BarrieredCell : public gc::Cell
static MOZ_ALWAYS_INLINE void readBarrier(T *thing) { static MOZ_ALWAYS_INLINE void readBarrier(T *thing) {
#ifdef JSGC_INCREMENTAL #ifdef JSGC_INCREMENTAL
JS_ASSERT(!CurrentThreadIsIonCompiling()); JS_ASSERT(!CurrentThreadIsIonCompiling());
JS_ASSERT(!T::isNullLike(thing));
JS::shadow::Zone *shadowZone = thing->shadowZoneFromAnyThread(); JS::shadow::Zone *shadowZone = thing->shadowZoneFromAnyThread();
if (shadowZone->needsIncrementalBarrier()) { if (shadowZone->needsIncrementalBarrier()) {
MOZ_ASSERT(!RuntimeFromMainThreadIsHeapMajorCollecting(shadowZone)); MOZ_ASSERT(!RuntimeFromMainThreadIsHeapMajorCollecting(shadowZone));
@ -213,6 +268,8 @@ class BarrieredCell : public gc::Cell
js::gc::MarkUnbarriered<T>(shadowZone->barrierTracer(), &tmp, "read barrier"); js::gc::MarkUnbarriered<T>(shadowZone->barrierTracer(), &tmp, "read barrier");
JS_ASSERT(tmp == thing); JS_ASSERT(tmp == thing);
} }
if (JS::GCThingIsMarkedGray(thing))
JS::UnmarkGrayGCThingRecursively(thing, MapTypeToTraceKind<T>::kind);
#endif #endif
} }
@ -771,6 +828,10 @@ class ReadBarriered
return value; return value;
} }
T unbarrieredGet() const {
return value;
}
operator T() const { return get(); } operator T() const { return get(); }
T &operator*() const { return *get(); } T &operator*() const { return *get(); }

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

@ -1142,7 +1142,7 @@ ScanBaseShape(GCMarker *gcmarker, BaseShape *base)
if (JSObject *parent = base->getObjectParent()) { if (JSObject *parent = base->getObjectParent()) {
MaybePushMarkStackBetweenSlices(gcmarker, parent); MaybePushMarkStackBetweenSlices(gcmarker, parent);
} else if (GlobalObject *global = base->compartment()->maybeGlobal()) { } else if (GlobalObject *global = base->compartment()->unsafeUnbarrieredMaybeGlobal()) {
PushMarkStack(gcmarker, global); PushMarkStack(gcmarker, global);
} }
@ -1961,10 +1961,13 @@ UnmarkGrayChildren(JSTracer *trc, void **thingp, JSGCTraceKind kind)
JS_FRIEND_API(bool) JS_FRIEND_API(bool)
JS::UnmarkGrayGCThingRecursively(void *thing, JSGCTraceKind kind) JS::UnmarkGrayGCThingRecursively(void *thing, JSGCTraceKind kind)
{ {
JS_ASSERT(kind != JSTRACE_SHAPE);
JSRuntime *rt = static_cast<Cell *>(thing)->runtimeFromMainThread(); JSRuntime *rt = static_cast<Cell *>(thing)->runtimeFromMainThread();
// When the ReadBarriered type is used in a HashTable, it is difficult or
// impossible to suppress the implicit cast operator while iterating for GC.
if (rt->isHeapBusy())
return false;
bool unmarkedArg = false; bool unmarkedArg = false;
if (!IsInsideNursery(static_cast<Cell *>(thing))) { if (!IsInsideNursery(static_cast<Cell *>(thing))) {
if (!JS::GCThingIsMarkedGray(thing)) if (!JS::GCThingIsMarkedGray(thing))

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

@ -183,6 +183,9 @@ struct JSCompartment
*/ */
inline js::GlobalObject *maybeGlobal() const; inline js::GlobalObject *maybeGlobal() const;
/* An unbarriered getter for use while tracing. */
inline js::GlobalObject *unsafeUnbarrieredMaybeGlobal() const;
inline void initGlobal(js::GlobalObject &global); inline void initGlobal(js::GlobalObject &global);
public: public:

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

@ -28,6 +28,12 @@ JSCompartment::maybeGlobal() const
return global_; return global_;
} }
js::GlobalObject *
JSCompartment::unsafeUnbarrieredMaybeGlobal() const
{
return *global_.unsafeGet();
}
js::AutoCompartment::AutoCompartment(ExclusiveContext *cx, JSObject *target) js::AutoCompartment::AutoCompartment(ExclusiveContext *cx, JSObject *target)
: cx_(cx), : cx_(cx),
origin_(cx->compartment_) origin_(cx->compartment_)

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

@ -4520,7 +4520,7 @@ GCRuntime::endSweepPhase(JSGCInvocationKind gckind, bool lastGC)
for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) { for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) {
if (e.front().key().kind != CrossCompartmentKey::StringWrapper) if (e.front().key().kind != CrossCompartmentKey::StringWrapper)
AssertNotOnGrayList(&e.front().value().get().toObject()); AssertNotOnGrayList(&e.front().value().unbarrieredGet().toObject());
} }
} }
#endif #endif

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

@ -20,32 +20,8 @@
#include "js/SliceBudget.h" #include "js/SliceBudget.h"
#include "js/Vector.h" #include "js/Vector.h"
class JSAtom;
struct JSCompartment;
class JSFlatString;
class JSLinearString;
namespace JS {
class Symbol;
} /* namespace JS */
namespace js { namespace js {
class ArgumentsObject;
class ArrayBufferObject;
class ArrayBufferViewObject;
class SharedArrayBufferObject;
class BaseShape;
class DebugScopeObject;
class GlobalObject;
class LazyScript;
class Nursery;
class PropertyName;
class SavedFrame;
class ScopeObject;
class Shape;
class UnownedBaseShape;
namespace gc { namespace gc {
class ForkJoinNursery; class ForkJoinNursery;
} }
@ -104,32 +80,6 @@ MapAllocToTraceKind(AllocKind kind)
return map[kind]; return map[kind];
} }
template <typename T> struct MapTypeToTraceKind {};
template <> struct MapTypeToTraceKind<ObjectImpl> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<JSObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<JSFunction> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<ArgumentsObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<ArrayBufferObject>{ static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<ArrayBufferViewObject>{ static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<SharedArrayBufferObject>{ static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<DebugScopeObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<GlobalObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<ScopeObject> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<SavedFrame> { static const JSGCTraceKind kind = JSTRACE_OBJECT; };
template <> struct MapTypeToTraceKind<JSScript> { static const JSGCTraceKind kind = JSTRACE_SCRIPT; };
template <> struct MapTypeToTraceKind<LazyScript> { static const JSGCTraceKind kind = JSTRACE_LAZY_SCRIPT; };
template <> struct MapTypeToTraceKind<Shape> { static const JSGCTraceKind kind = JSTRACE_SHAPE; };
template <> struct MapTypeToTraceKind<BaseShape> { static const JSGCTraceKind kind = JSTRACE_BASE_SHAPE; };
template <> struct MapTypeToTraceKind<UnownedBaseShape> { static const JSGCTraceKind kind = JSTRACE_BASE_SHAPE; };
template <> struct MapTypeToTraceKind<types::TypeObject>{ static const JSGCTraceKind kind = JSTRACE_TYPE_OBJECT; };
template <> struct MapTypeToTraceKind<JSAtom> { static const JSGCTraceKind kind = JSTRACE_STRING; };
template <> struct MapTypeToTraceKind<JSString> { static const JSGCTraceKind kind = JSTRACE_STRING; };
template <> struct MapTypeToTraceKind<JSFlatString> { static const JSGCTraceKind kind = JSTRACE_STRING; };
template <> struct MapTypeToTraceKind<JSLinearString> { static const JSGCTraceKind kind = JSTRACE_STRING; };
template <> struct MapTypeToTraceKind<JS::Symbol> { static const JSGCTraceKind kind = JSTRACE_SYMBOL; };
template <> struct MapTypeToTraceKind<PropertyName> { static const JSGCTraceKind kind = JSTRACE_STRING; };
template <> struct MapTypeToTraceKind<jit::JitCode> { static const JSGCTraceKind kind = JSTRACE_JITCODE; };
/* Return a printable string for the given kind, for diagnostic purposes. */ /* Return a printable string for the given kind, for diagnostic purposes. */
const char * const char *
TraceKindAsAscii(JSGCTraceKind kind); TraceKindAsAscii(JSGCTraceKind kind);

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

@ -2322,7 +2322,7 @@ TypeCompartment::markSetsUnknown(JSContext *cx, TypeObject *target)
} }
for (gc::ZoneCellIter i(cx->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) { for (gc::ZoneCellIter i(cx->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
RootedScript script(cx, i.get<JSScript>()); JSScript *script = i.get<JSScript>();
if (script->types) { if (script->types) {
unsigned count = TypeScript::NumTypeSets(script); unsigned count = TypeScript::NumTypeSets(script);
StackTypeSet *typeArray = script->types->typeArray(); StackTypeSet *typeArray = script->types->typeArray();
@ -4122,7 +4122,7 @@ TypeCompartment::sweep(FreeOp *fop)
bool remove = false; bool remove = false;
TypeObject *typeObject = nullptr; TypeObject *typeObject = nullptr;
if (!key.type.isUnknown() && key.type.isTypeObject()) { if (!key.type.isUnknown() && key.type.isTypeObject()) {
typeObject = key.type.typeObject(); typeObject = key.type.typeObjectNoBarrier();
if (IsTypeObjectAboutToBeFinalized(&typeObject)) if (IsTypeObjectAboutToBeFinalized(&typeObject))
remove = true; remove = true;
} }
@ -4131,7 +4131,7 @@ TypeCompartment::sweep(FreeOp *fop)
if (remove) { if (remove) {
e.removeFront(); e.removeFront();
} else if (typeObject && typeObject != key.type.typeObject()) { } else if (typeObject && typeObject != key.type.typeObjectNoBarrier()) {
ArrayTableKey newKey; ArrayTableKey newKey;
newKey.type = Type::ObjectType(typeObject); newKey.type = Type::ObjectType(typeObject);
newKey.proto = key.proto; newKey.proto = key.proto;
@ -4160,10 +4160,10 @@ TypeCompartment::sweep(FreeOp *fop)
JS_ASSERT(!entry.types[i].isSingleObject()); JS_ASSERT(!entry.types[i].isSingleObject());
TypeObject *typeObject = nullptr; TypeObject *typeObject = nullptr;
if (entry.types[i].isTypeObject()) { if (entry.types[i].isTypeObject()) {
typeObject = entry.types[i].typeObject(); typeObject = entry.types[i].typeObjectNoBarrier();
if (IsTypeObjectAboutToBeFinalized(&typeObject)) if (IsTypeObjectAboutToBeFinalized(&typeObject))
remove = true; remove = true;
else if (typeObject != entry.types[i].typeObject()) else if (typeObject != entry.types[i].typeObjectNoBarrier())
entry.types[i] = Type::ObjectType(typeObject); entry.types[i] = Type::ObjectType(typeObject);
} }
} }
@ -4203,7 +4203,7 @@ JSCompartment::sweepNewTypeObjectTable(TypeObjectWithNewScriptSet &table)
e.removeFront(); e.removeFront();
} else if (entry.newFunction && IsObjectAboutToBeFinalized(&entry.newFunction)) { } else if (entry.newFunction && IsObjectAboutToBeFinalized(&entry.newFunction)) {
e.removeFront(); e.removeFront();
} else if (entry.object != e.front().object) { } else if (entry.object.unbarrieredGet() != e.front().object.unbarrieredGet()) {
TypeObjectWithNewScriptSet::Lookup lookup(entry.object->clasp(), TypeObjectWithNewScriptSet::Lookup lookup(entry.object->clasp(),
entry.object->proto(), entry.object->proto(),
entry.newFunction); entry.newFunction);

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

@ -664,7 +664,13 @@ JSObject::global() const
while (JSObject *parent = obj->getParent()) while (JSObject *parent = obj->getParent())
obj = parent; obj = parent;
#endif #endif
return *compartment()->maybeGlobal(); /*
* The global is read-barriered so that it is kept live by access through
* the JSCompartment. When accessed through a JSObject, however, the global
* will be already be kept live by the black JSObject's parent pointer, so
* does not need to be read-barriered.
*/
return *compartment()->unsafeUnbarrieredMaybeGlobal();
} }
inline bool inline bool

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

@ -145,10 +145,10 @@ PropertyTree::getChild(ExclusiveContext *cx, Shape *parentArg, StackShape &unroo
if (kidp->isShape()) { if (kidp->isShape()) {
Shape *kid = kidp->toShape(); Shape *kid = kidp->toShape();
if (kid->matches(unrootedChild)) if (kid->matches(unrootedChild))
existingShape = kid; existingShape = kid;
} else if (kidp->isHash()) { } else if (kidp->isHash()) {
if (KidsHash::Ptr p = kidp->toHash()->lookup(unrootedChild)) if (KidsHash::Ptr p = kidp->toHash()->lookup(unrootedChild))
existingShape = *p; existingShape = *p;
} else { } else {
/* If kidp->isNull(), we always insert. */ /* If kidp->isNull(), we always insert. */
} }
@ -174,6 +174,8 @@ PropertyTree::getChild(ExclusiveContext *cx, Shape *parentArg, StackShape &unroo
JS_ASSERT(parent->isMarked()); JS_ASSERT(parent->isMarked());
parent->removeChild(existingShape); parent->removeChild(existingShape);
existingShape = nullptr; existingShape = nullptr;
} else if (existingShape->isMarked(gc::GRAY)) {
JS::UnmarkGrayGCThingRecursively(existingShape, JSTRACE_SHAPE);
} }
} }
#endif #endif

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

@ -271,10 +271,6 @@ WeakMap_get_impl(JSContext *cx, CallArgs args)
if (ObjectValueMap *map = args.thisv().toObject().as<WeakMapObject>().getMap()) { if (ObjectValueMap *map = args.thisv().toObject().as<WeakMapObject>().getMap()) {
if (ObjectValueMap::Ptr ptr = map->lookup(key)) { if (ObjectValueMap::Ptr ptr = map->lookup(key)) {
// Read barrier to prevent an incorrectly gray value from escaping the
// weak map. See the comment before UnmarkGrayChildren in gc/Marking.cpp
ExposeValueToActiveJS(ptr->value().get());
args.rval().set(ptr->value()); args.rval().set(ptr->value());
return true; return true;
} }
@ -450,6 +446,7 @@ JS_NondeterministicGetWeakMapKeys(JSContext *cx, HandleObject objArg, MutableHan
// Prevent GC from mutating the weakmap while iterating. // Prevent GC from mutating the weakmap while iterating.
AutoSuppressGC suppress(cx); AutoSuppressGC suppress(cx);
for (ObjectValueMap::Base::Range r = map->all(); !r.empty(); r.popFront()) { for (ObjectValueMap::Base::Range r = map->all(); !r.empty(); r.popFront()) {
JS::ExposeObjectToActiveJS(r.front().key());
RootedObject key(cx, r.front().key()); RootedObject key(cx, r.front().key());
if (!cx->compartment()->wrap(cx, &key)) if (!cx->compartment()->wrap(cx, &key))
return false; return false;

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

@ -111,6 +111,8 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
typedef typename Base::Enum Enum; typedef typename Base::Enum Enum;
typedef typename Base::Lookup Lookup; typedef typename Base::Lookup Lookup;
typedef typename Base::Range Range; typedef typename Base::Range Range;
typedef typename Base::Ptr Ptr;
typedef typename Base::AddPtr AddPtr;
explicit WeakMap(JSContext *cx, JSObject *memOf = nullptr) explicit WeakMap(JSContext *cx, JSObject *memOf = nullptr)
: Base(cx->runtime()), WeakMapBase(memOf, cx->compartment()) { } : Base(cx->runtime()), WeakMapBase(memOf, cx->compartment()) { }
@ -124,7 +126,34 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
return true; return true;
} }
// Overwritten to add a read barrier to prevent an incorrectly gray value
// from escaping the weak map. See the comment before UnmarkGrayChildren in
// gc/Marking.cpp
Ptr lookup(const Lookup &l) const {
Ptr p = Base::lookup(l);
if (p)
exposeGCThingToActiveJS(p->value());
return p;
}
AddPtr lookupForAdd(const Lookup &l) const {
AddPtr p = Base::lookupForAdd(l);
if (p)
exposeGCThingToActiveJS(p->value());
return p;
}
Ptr lookupWithDefault(const Key &k, const Value &defaultValue) {
Ptr p = Base::lookupWithDefault(k, defaultValue);
if (p)
exposeGCThingToActiveJS(p->value());
return p;
}
private: private:
void exposeGCThingToActiveJS(const JS::Value &v) const { JS::ExposeValueToActiveJS(v); }
void exposeGCThingToActiveJS(JSObject *obj) const { JS::ExposeObjectToActiveJS(obj); }
bool markValue(JSTracer *trc, Value *x) { bool markValue(JSTracer *trc, Value *x) {
if (gc::IsMarked(x)) if (gc::IsMarked(x))
return false; return false;

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

@ -18,6 +18,7 @@
#include "frontend/BytecodeCompiler.h" #include "frontend/BytecodeCompiler.h"
#include "gc/Marking.h" #include "gc/Marking.h"
#include "jit/BaselineJIT.h" #include "jit/BaselineJIT.h"
#include "js/GCAPI.h"
#include "js/Vector.h" #include "js/Vector.h"
#include "vm/ArgumentsObject.h" #include "vm/ArgumentsObject.h"
#include "vm/DebuggerMemory.h" #include "vm/DebuggerMemory.h"
@ -1426,10 +1427,13 @@ Debugger::slowPathOnNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global
AutoObjectVector watchers(cx); AutoObjectVector watchers(cx);
for (JSCList *link = JS_LIST_HEAD(&cx->runtime()->onNewGlobalObjectWatchers); for (JSCList *link = JS_LIST_HEAD(&cx->runtime()->onNewGlobalObjectWatchers);
link != &cx->runtime()->onNewGlobalObjectWatchers; link != &cx->runtime()->onNewGlobalObjectWatchers;
link = JS_NEXT_LINK(link)) { link = JS_NEXT_LINK(link))
{
Debugger *dbg = fromOnNewGlobalObjectWatchersLink(link); Debugger *dbg = fromOnNewGlobalObjectWatchersLink(link);
JS_ASSERT(dbg->observesNewGlobalObject()); JS_ASSERT(dbg->observesNewGlobalObject());
if (!watchers.append(dbg->object)) JSObject *obj = dbg->object;
JS::ExposeObjectToActiveJS(obj);
if (!watchers.append(obj))
return; return;
} }
@ -2674,6 +2678,10 @@ class Debugger::ScriptQuery {
return false; return false;
} }
/* We cannot touch the gray bits while isHeapBusy, so do this now. */
for (JSScript **i = vector->begin(); i != vector->end(); ++i)
JS::ExposeScriptToActiveJS(*i);
/* /*
* For most queries, we just accumulate results in 'vector' as we find * For most queries, we just accumulate results in 'vector' as we find
* them. But if this is an 'innermost' query, then we've accumulated the * them. But if this is an 'innermost' query, then we've accumulated the
@ -2683,7 +2691,9 @@ class Debugger::ScriptQuery {
if (innermost) { if (innermost) {
for (CompartmentToScriptMap::Range r = innermostForCompartment.all(); for (CompartmentToScriptMap::Range r = innermostForCompartment.all();
!r.empty(); !r.empty();
r.popFront()) { r.popFront())
{
JS::ExposeScriptToActiveJS(r.front().value());
if (!v->append(r.front().value())) { if (!v->append(r.front().value())) {
js_ReportOutOfMemory(cx); js_ReportOutOfMemory(cx);
return false; return false;

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

@ -452,8 +452,8 @@ SavedStacks::sweep(JSRuntime *rt)
sweepPCLocationMap(); sweepPCLocationMap();
if (savedFrameProto && IsObjectAboutToBeFinalized(&savedFrameProto)) { if (savedFrameProto && IsObjectAboutToBeFinalized(savedFrameProto.unsafeGet())) {
savedFrameProto = nullptr; savedFrameProto.set(nullptr);
} }
} }
@ -593,9 +593,11 @@ SavedStacks::getOrCreateSavedFramePrototype(JSContext *cx)
|| !JS_DefineProperties(cx, proto, SavedFrame::properties) || !JS_DefineProperties(cx, proto, SavedFrame::properties)
|| !JS_DefineFunctions(cx, proto, SavedFrame::methods) || !JS_DefineFunctions(cx, proto, SavedFrame::methods)
|| !JSObject::freeze(cx, proto)) || !JSObject::freeze(cx, proto))
{
return nullptr; return nullptr;
}
savedFrameProto = proto; savedFrameProto.set(proto);
// The only object with the SavedFrame::class_ that doesn't have a source // The only object with the SavedFrame::class_ that doesn't have a source
// should be the prototype. // should be the prototype.
savedFrameProto->setReservedSlot(SavedFrame::JSSLOT_SOURCE, NullValue()); savedFrameProto->setReservedSlot(SavedFrame::JSSLOT_SOURCE, NullValue());

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

@ -115,7 +115,7 @@ class SavedStacks {
private: private:
SavedFrame::Set frames; SavedFrame::Set frames;
JSObject *savedFrameProto; ReadBarrieredObject savedFrameProto;
bool insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFrame frame, bool insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFrame frame,
unsigned maxFrameCount = 0); unsigned maxFrameCount = 0);

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

@ -1528,7 +1528,7 @@ JSCompartment::sweepBaseShapeTable()
if (baseShapes.initialized()) { if (baseShapes.initialized()) {
for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) { for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) {
UnownedBaseShape *base = e.front(); UnownedBaseShape *base = e.front().unbarrieredGet();
if (IsBaseShapeAboutToBeFinalized(&base)) if (IsBaseShapeAboutToBeFinalized(&base))
e.removeFront(); e.removeFront();
} }
@ -1816,7 +1816,7 @@ JSCompartment::sweepInitialShapeTable()
if (initialShapes.initialized()) { if (initialShapes.initialized()) {
for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) { for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) {
const InitialShapeEntry &entry = e.front(); const InitialShapeEntry &entry = e.front();
Shape *shape = entry.shape; Shape *shape = entry.shape.unbarrieredGet();
JSObject *proto = entry.proto.raw(); JSObject *proto = entry.proto.raw();
if (IsShapeAboutToBeFinalized(&shape) || (entry.proto.isObject() && IsObjectAboutToBeFinalized(&proto))) { if (IsShapeAboutToBeFinalized(&shape) || (entry.proto.isObject() && IsObjectAboutToBeFinalized(&proto))) {
e.removeFront(); e.removeFront();
@ -1826,7 +1826,7 @@ JSCompartment::sweepInitialShapeTable()
JS_ASSERT(!parent || !IsObjectAboutToBeFinalized(&parent)); JS_ASSERT(!parent || !IsObjectAboutToBeFinalized(&parent));
JS_ASSERT(parent == shape->getObjectParent()); JS_ASSERT(parent == shape->getObjectParent());
#endif #endif
if (shape != entry.shape || proto != entry.proto.raw()) { if (shape != entry.shape.unbarrieredGet() || proto != entry.proto.raw()) {
ReadBarrieredShape readBarrieredShape(shape); ReadBarrieredShape readBarrieredShape(shape);
InitialShapeEntry newKey(readBarrieredShape, TaggedProto(proto)); InitialShapeEntry newKey(readBarrieredShape, TaggedProto(proto));
e.rekeyFront(newKey.getLookup(), newKey); e.rekeyFront(newKey.getLookup(), newKey);

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

@ -369,7 +369,8 @@ InterpreterFrame::mark(JSTracer *trc)
} }
if (IS_GC_MARKING_TRACER(trc)) if (IS_GC_MARKING_TRACER(trc))
script()->compartment()->zone()->active = true; script()->compartment()->zone()->active = true;
gc::MarkValueUnbarriered(trc, returnValue().address(), "rval"); if (hasReturnValue())
gc::MarkValueUnbarriered(trc, &rval_, "rval");
} }
void void