From 68b8d91b1feddf1d043625c36c5bc5fd7cac8cf2 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Mon, 28 Jul 2014 10:16:56 -0700 Subject: [PATCH] Bug 1024250; r=billm --- js/src/gc/Barrier.h | 61 +++++++++++++++++++++++++++++++++++ js/src/gc/Marking.cpp | 9 ++++-- js/src/jscompartment.h | 3 ++ js/src/jscompartmentinlines.h | 6 ++++ js/src/jsgc.cpp | 2 +- js/src/jsgc.h | 50 ---------------------------- js/src/jsinfer.cpp | 12 +++---- js/src/jsobjinlines.h | 8 ++++- js/src/jspropertytree.cpp | 6 ++-- js/src/jsweakmap.cpp | 5 +-- js/src/jsweakmap.h | 29 +++++++++++++++++ js/src/vm/Debugger.cpp | 16 +++++++-- js/src/vm/SavedStacks.cpp | 8 +++-- js/src/vm/SavedStacks.h | 2 +- js/src/vm/Shape.cpp | 6 ++-- js/src/vm/Stack.cpp | 3 +- 16 files changed, 148 insertions(+), 78 deletions(-) diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index 5d0fe1c72e94..34468f74b295 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -151,12 +151,40 @@ */ class JSAtom; +struct JSCompartment; class JSFlatString; class JSLinearString; +namespace JS { +class Symbol; +} + 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 SavedFrame; +class ScopeObject; +class ScriptSourceObject; +class Shape; +class UnownedBaseShape; + +namespace types { +struct TypeObject; +} + +namespace jit { +class JitCode; +} #ifdef DEBUG bool @@ -173,6 +201,32 @@ StringIsPermanentAtom(JSString *str); namespace gc { +template struct MapTypeToTraceKind {}; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; +template <> struct MapTypeToTraceKind{ static const JSGCTraceKind kind = JSTRACE_OBJECT; }; +template <> struct MapTypeToTraceKind{ static const JSGCTraceKind kind = JSTRACE_OBJECT; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_BASE_SHAPE; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_SYMBOL; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_SCRIPT; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_LAZY_SCRIPT; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_SHAPE; }; +template <> struct MapTypeToTraceKind{ static const JSGCTraceKind kind = JSTRACE_OBJECT; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_BASE_SHAPE; }; +template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_JITCODE; }; +template <> struct MapTypeToTraceKind{ static const JSGCTraceKind kind = JSTRACE_TYPE_OBJECT; }; + template void 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) { #ifdef JSGC_INCREMENTAL JS_ASSERT(!CurrentThreadIsIonCompiling()); + JS_ASSERT(!T::isNullLike(thing)); JS::shadow::Zone *shadowZone = thing->shadowZoneFromAnyThread(); if (shadowZone->needsIncrementalBarrier()) { MOZ_ASSERT(!RuntimeFromMainThreadIsHeapMajorCollecting(shadowZone)); @@ -213,6 +268,8 @@ class BarrieredCell : public gc::Cell js::gc::MarkUnbarriered(shadowZone->barrierTracer(), &tmp, "read barrier"); JS_ASSERT(tmp == thing); } + if (JS::GCThingIsMarkedGray(thing)) + JS::UnmarkGrayGCThingRecursively(thing, MapTypeToTraceKind::kind); #endif } @@ -771,6 +828,10 @@ class ReadBarriered return value; } + T unbarrieredGet() const { + return value; + } + operator T() const { return get(); } T &operator*() const { return *get(); } diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 3ffff65c2dfd..48bd3df22a06 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -1142,7 +1142,7 @@ ScanBaseShape(GCMarker *gcmarker, BaseShape *base) if (JSObject *parent = base->getObjectParent()) { MaybePushMarkStackBetweenSlices(gcmarker, parent); - } else if (GlobalObject *global = base->compartment()->maybeGlobal()) { + } else if (GlobalObject *global = base->compartment()->unsafeUnbarrieredMaybeGlobal()) { PushMarkStack(gcmarker, global); } @@ -1961,10 +1961,13 @@ UnmarkGrayChildren(JSTracer *trc, void **thingp, JSGCTraceKind kind) JS_FRIEND_API(bool) JS::UnmarkGrayGCThingRecursively(void *thing, JSGCTraceKind kind) { - JS_ASSERT(kind != JSTRACE_SHAPE); - JSRuntime *rt = static_cast(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; if (!IsInsideNursery(static_cast(thing))) { if (!JS::GCThingIsMarkedGray(thing)) diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index b6c467c98378..ffdc97eb6e58 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -183,6 +183,9 @@ struct JSCompartment */ inline js::GlobalObject *maybeGlobal() const; + /* An unbarriered getter for use while tracing. */ + inline js::GlobalObject *unsafeUnbarrieredMaybeGlobal() const; + inline void initGlobal(js::GlobalObject &global); public: diff --git a/js/src/jscompartmentinlines.h b/js/src/jscompartmentinlines.h index efffb52cb394..dc393de7e664 100644 --- a/js/src/jscompartmentinlines.h +++ b/js/src/jscompartmentinlines.h @@ -28,6 +28,12 @@ JSCompartment::maybeGlobal() const return global_; } +js::GlobalObject * +JSCompartment::unsafeUnbarrieredMaybeGlobal() const +{ + return *global_.unsafeGet(); +} + js::AutoCompartment::AutoCompartment(ExclusiveContext *cx, JSObject *target) : cx_(cx), origin_(cx->compartment_) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index d416c7e83e7a..f85a1ee7d9c2 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -4520,7 +4520,7 @@ GCRuntime::endSweepPhase(JSGCInvocationKind gckind, bool lastGC) for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) { if (e.front().key().kind != CrossCompartmentKey::StringWrapper) - AssertNotOnGrayList(&e.front().value().get().toObject()); + AssertNotOnGrayList(&e.front().value().unbarrieredGet().toObject()); } } #endif diff --git a/js/src/jsgc.h b/js/src/jsgc.h index d761d97870b8..3f3f4265b88b 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -20,32 +20,8 @@ #include "js/SliceBudget.h" #include "js/Vector.h" -class JSAtom; -struct JSCompartment; -class JSFlatString; -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 PropertyName; -class SavedFrame; -class ScopeObject; -class Shape; -class UnownedBaseShape; - namespace gc { class ForkJoinNursery; } @@ -104,32 +80,6 @@ MapAllocToTraceKind(AllocKind kind) return map[kind]; } -template struct MapTypeToTraceKind {}; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; -template <> struct MapTypeToTraceKind{ static const JSGCTraceKind kind = JSTRACE_OBJECT; }; -template <> struct MapTypeToTraceKind{ static const JSGCTraceKind kind = JSTRACE_OBJECT; }; -template <> struct MapTypeToTraceKind{ static const JSGCTraceKind kind = JSTRACE_OBJECT; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_OBJECT; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_SCRIPT; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_LAZY_SCRIPT; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_SHAPE; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_BASE_SHAPE; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_BASE_SHAPE; }; -template <> struct MapTypeToTraceKind{ static const JSGCTraceKind kind = JSTRACE_TYPE_OBJECT; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_SYMBOL; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_STRING; }; -template <> struct MapTypeToTraceKind { static const JSGCTraceKind kind = JSTRACE_JITCODE; }; - /* Return a printable string for the given kind, for diagnostic purposes. */ const char * TraceKindAsAscii(JSGCTraceKind kind); diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index f2fa0719c87c..4d4254ca93cd 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -2322,7 +2322,7 @@ TypeCompartment::markSetsUnknown(JSContext *cx, TypeObject *target) } for (gc::ZoneCellIter i(cx->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) { - RootedScript script(cx, i.get()); + JSScript *script = i.get(); if (script->types) { unsigned count = TypeScript::NumTypeSets(script); StackTypeSet *typeArray = script->types->typeArray(); @@ -4122,7 +4122,7 @@ TypeCompartment::sweep(FreeOp *fop) bool remove = false; TypeObject *typeObject = nullptr; if (!key.type.isUnknown() && key.type.isTypeObject()) { - typeObject = key.type.typeObject(); + typeObject = key.type.typeObjectNoBarrier(); if (IsTypeObjectAboutToBeFinalized(&typeObject)) remove = true; } @@ -4131,7 +4131,7 @@ TypeCompartment::sweep(FreeOp *fop) if (remove) { e.removeFront(); - } else if (typeObject && typeObject != key.type.typeObject()) { + } else if (typeObject && typeObject != key.type.typeObjectNoBarrier()) { ArrayTableKey newKey; newKey.type = Type::ObjectType(typeObject); newKey.proto = key.proto; @@ -4160,10 +4160,10 @@ TypeCompartment::sweep(FreeOp *fop) JS_ASSERT(!entry.types[i].isSingleObject()); TypeObject *typeObject = nullptr; if (entry.types[i].isTypeObject()) { - typeObject = entry.types[i].typeObject(); + typeObject = entry.types[i].typeObjectNoBarrier(); if (IsTypeObjectAboutToBeFinalized(&typeObject)) remove = true; - else if (typeObject != entry.types[i].typeObject()) + else if (typeObject != entry.types[i].typeObjectNoBarrier()) entry.types[i] = Type::ObjectType(typeObject); } } @@ -4203,7 +4203,7 @@ JSCompartment::sweepNewTypeObjectTable(TypeObjectWithNewScriptSet &table) e.removeFront(); } else if (entry.newFunction && IsObjectAboutToBeFinalized(&entry.newFunction)) { e.removeFront(); - } else if (entry.object != e.front().object) { + } else if (entry.object.unbarrieredGet() != e.front().object.unbarrieredGet()) { TypeObjectWithNewScriptSet::Lookup lookup(entry.object->clasp(), entry.object->proto(), entry.newFunction); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 7f0bbc808a31..8758514a8450 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -664,7 +664,13 @@ JSObject::global() const while (JSObject *parent = obj->getParent()) obj = parent; #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 diff --git a/js/src/jspropertytree.cpp b/js/src/jspropertytree.cpp index eaa91342f364..6c73fda89e4e 100644 --- a/js/src/jspropertytree.cpp +++ b/js/src/jspropertytree.cpp @@ -145,10 +145,10 @@ PropertyTree::getChild(ExclusiveContext *cx, Shape *parentArg, StackShape &unroo if (kidp->isShape()) { Shape *kid = kidp->toShape(); if (kid->matches(unrootedChild)) - existingShape = kid; + existingShape = kid; } else if (kidp->isHash()) { if (KidsHash::Ptr p = kidp->toHash()->lookup(unrootedChild)) - existingShape = *p; + existingShape = *p; } else { /* If kidp->isNull(), we always insert. */ } @@ -174,6 +174,8 @@ PropertyTree::getChild(ExclusiveContext *cx, Shape *parentArg, StackShape &unroo JS_ASSERT(parent->isMarked()); parent->removeChild(existingShape); existingShape = nullptr; + } else if (existingShape->isMarked(gc::GRAY)) { + JS::UnmarkGrayGCThingRecursively(existingShape, JSTRACE_SHAPE); } } #endif diff --git a/js/src/jsweakmap.cpp b/js/src/jsweakmap.cpp index 277b84bc79ae..2783658a0f9a 100644 --- a/js/src/jsweakmap.cpp +++ b/js/src/jsweakmap.cpp @@ -271,10 +271,6 @@ WeakMap_get_impl(JSContext *cx, CallArgs args) if (ObjectValueMap *map = args.thisv().toObject().as().getMap()) { 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()); return true; } @@ -450,6 +446,7 @@ JS_NondeterministicGetWeakMapKeys(JSContext *cx, HandleObject objArg, MutableHan // Prevent GC from mutating the weakmap while iterating. AutoSuppressGC suppress(cx); for (ObjectValueMap::Base::Range r = map->all(); !r.empty(); r.popFront()) { + JS::ExposeObjectToActiveJS(r.front().key()); RootedObject key(cx, r.front().key()); if (!cx->compartment()->wrap(cx, &key)) return false; diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index 18a583b2ef40..690278be3a72 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -111,6 +111,8 @@ class WeakMap : public HashMap, publ typedef typename Base::Enum Enum; typedef typename Base::Lookup Lookup; typedef typename Base::Range Range; + typedef typename Base::Ptr Ptr; + typedef typename Base::AddPtr AddPtr; explicit WeakMap(JSContext *cx, JSObject *memOf = nullptr) : Base(cx->runtime()), WeakMapBase(memOf, cx->compartment()) { } @@ -124,7 +126,34 @@ class WeakMap : public HashMap, publ 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: + void exposeGCThingToActiveJS(const JS::Value &v) const { JS::ExposeValueToActiveJS(v); } + void exposeGCThingToActiveJS(JSObject *obj) const { JS::ExposeObjectToActiveJS(obj); } + bool markValue(JSTracer *trc, Value *x) { if (gc::IsMarked(x)) return false; diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index b7fada8b139b..065d8517acce 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -18,6 +18,7 @@ #include "frontend/BytecodeCompiler.h" #include "gc/Marking.h" #include "jit/BaselineJIT.h" +#include "js/GCAPI.h" #include "js/Vector.h" #include "vm/ArgumentsObject.h" #include "vm/DebuggerMemory.h" @@ -1426,10 +1427,13 @@ Debugger::slowPathOnNewGlobalObject(JSContext *cx, Handle global AutoObjectVector watchers(cx); for (JSCList *link = JS_LIST_HEAD(&cx->runtime()->onNewGlobalObjectWatchers); link != &cx->runtime()->onNewGlobalObjectWatchers; - link = JS_NEXT_LINK(link)) { + link = JS_NEXT_LINK(link)) + { Debugger *dbg = fromOnNewGlobalObjectWatchersLink(link); JS_ASSERT(dbg->observesNewGlobalObject()); - if (!watchers.append(dbg->object)) + JSObject *obj = dbg->object; + JS::ExposeObjectToActiveJS(obj); + if (!watchers.append(obj)) return; } @@ -2674,6 +2678,10 @@ class Debugger::ScriptQuery { 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 * them. But if this is an 'innermost' query, then we've accumulated the @@ -2683,7 +2691,9 @@ class Debugger::ScriptQuery { if (innermost) { for (CompartmentToScriptMap::Range r = innermostForCompartment.all(); !r.empty(); - r.popFront()) { + r.popFront()) + { + JS::ExposeScriptToActiveJS(r.front().value()); if (!v->append(r.front().value())) { js_ReportOutOfMemory(cx); return false; diff --git a/js/src/vm/SavedStacks.cpp b/js/src/vm/SavedStacks.cpp index fbf2255b638d..815b7e5d5d16 100644 --- a/js/src/vm/SavedStacks.cpp +++ b/js/src/vm/SavedStacks.cpp @@ -452,8 +452,8 @@ SavedStacks::sweep(JSRuntime *rt) sweepPCLocationMap(); - if (savedFrameProto && IsObjectAboutToBeFinalized(&savedFrameProto)) { - savedFrameProto = nullptr; + if (savedFrameProto && IsObjectAboutToBeFinalized(savedFrameProto.unsafeGet())) { + savedFrameProto.set(nullptr); } } @@ -593,9 +593,11 @@ SavedStacks::getOrCreateSavedFramePrototype(JSContext *cx) || !JS_DefineProperties(cx, proto, SavedFrame::properties) || !JS_DefineFunctions(cx, proto, SavedFrame::methods) || !JSObject::freeze(cx, proto)) + { return nullptr; + } - savedFrameProto = proto; + savedFrameProto.set(proto); // The only object with the SavedFrame::class_ that doesn't have a source // should be the prototype. savedFrameProto->setReservedSlot(SavedFrame::JSSLOT_SOURCE, NullValue()); diff --git a/js/src/vm/SavedStacks.h b/js/src/vm/SavedStacks.h index 4afcab4ee281..406975c0891a 100644 --- a/js/src/vm/SavedStacks.h +++ b/js/src/vm/SavedStacks.h @@ -115,7 +115,7 @@ class SavedStacks { private: SavedFrame::Set frames; - JSObject *savedFrameProto; + ReadBarrieredObject savedFrameProto; bool insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFrame frame, unsigned maxFrameCount = 0); diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index 705b74501fe5..ba461f1e585e 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1528,7 +1528,7 @@ JSCompartment::sweepBaseShapeTable() if (baseShapes.initialized()) { for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) { - UnownedBaseShape *base = e.front(); + UnownedBaseShape *base = e.front().unbarrieredGet(); if (IsBaseShapeAboutToBeFinalized(&base)) e.removeFront(); } @@ -1816,7 +1816,7 @@ JSCompartment::sweepInitialShapeTable() if (initialShapes.initialized()) { for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) { const InitialShapeEntry &entry = e.front(); - Shape *shape = entry.shape; + Shape *shape = entry.shape.unbarrieredGet(); JSObject *proto = entry.proto.raw(); if (IsShapeAboutToBeFinalized(&shape) || (entry.proto.isObject() && IsObjectAboutToBeFinalized(&proto))) { e.removeFront(); @@ -1826,7 +1826,7 @@ JSCompartment::sweepInitialShapeTable() JS_ASSERT(!parent || !IsObjectAboutToBeFinalized(&parent)); JS_ASSERT(parent == shape->getObjectParent()); #endif - if (shape != entry.shape || proto != entry.proto.raw()) { + if (shape != entry.shape.unbarrieredGet() || proto != entry.proto.raw()) { ReadBarrieredShape readBarrieredShape(shape); InitialShapeEntry newKey(readBarrieredShape, TaggedProto(proto)); e.rekeyFront(newKey.getLookup(), newKey); diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 560cead695b6..aa436b7d6b3b 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -369,7 +369,8 @@ InterpreterFrame::mark(JSTracer *trc) } if (IS_GC_MARKING_TRACER(trc)) script()->compartment()->zone()->active = true; - gc::MarkValueUnbarriered(trc, returnValue().address(), "rval"); + if (hasReturnValue()) + gc::MarkValueUnbarriered(trc, &rval_, "rval"); } void