зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1024250; r=billm
This commit is contained in:
Родитель
9bc76bfb73
Коммит
68b8d91b1f
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче