зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 465793bc6fcf (bug 1180017) for suspicion of causing bug 1188799
This commit is contained in:
Родитель
3f86b89c01
Коммит
25a2a75a56
|
@ -101,8 +101,8 @@ DebugWrapperTraceCallback(JS::GCCellPtr aPtr, const char* aName, void* aClosure)
|
|||
{
|
||||
DebugWrapperTraversalCallback* callback =
|
||||
static_cast<DebugWrapperTraversalCallback*>(aClosure);
|
||||
if (aPtr.is<JSObject>()) {
|
||||
callback->NoteJSObject(&aPtr.as<JSObject>());
|
||||
if (aPtr.isObject()) {
|
||||
callback->NoteJSObject(aPtr.toObject());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|||
static void
|
||||
UnmarkXBLJSObject(JS::GCCellPtr aPtr, const char* aName, void* aClosure)
|
||||
{
|
||||
JS::ExposeObjectToActiveJS(&aPtr.as<JSObject>());
|
||||
JS::ExposeObjectToActiveJS(aPtr.toObject());
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
|
|
|
@ -163,10 +163,12 @@ class JS_FRIEND_API(GCCellPtr)
|
|||
MOZ_IMPLICIT GCCellPtr(decltype(nullptr)) : ptr(checkedCast(nullptr, JS::TraceKind::Null)) {}
|
||||
|
||||
// Construction from an explicit type.
|
||||
template <typename T>
|
||||
explicit GCCellPtr(T* p) : ptr(checkedCast(p, JS::MapTypeToTraceKind<T>::kind)) { }
|
||||
explicit GCCellPtr(JSFunction* p) : ptr(checkedCast(p, JS::TraceKind::Object)) { }
|
||||
explicit GCCellPtr(JSObject* obj) : ptr(checkedCast(obj, JS::TraceKind::Object)) { }
|
||||
explicit GCCellPtr(JSFunction* fun) : ptr(checkedCast(fun, JS::TraceKind::Object)) { }
|
||||
explicit GCCellPtr(JSString* str) : ptr(checkedCast(str, JS::TraceKind::String)) { }
|
||||
explicit GCCellPtr(JSFlatString* str) : ptr(checkedCast(str, JS::TraceKind::String)) { }
|
||||
explicit GCCellPtr(JS::Symbol* sym) : ptr(checkedCast(sym, JS::TraceKind::Symbol)) { }
|
||||
explicit GCCellPtr(JSScript* script) : ptr(checkedCast(script, JS::TraceKind::Script)) { }
|
||||
explicit GCCellPtr(const Value& v);
|
||||
|
||||
JS::TraceKind kind() const {
|
||||
|
@ -183,22 +185,31 @@ class JS_FRIEND_API(GCCellPtr)
|
|||
}
|
||||
|
||||
// Simplify checks to the kind.
|
||||
template <typename T>
|
||||
bool is() const { return kind() == JS::MapTypeToTraceKind<T>::kind; }
|
||||
bool isObject() const { return kind() == JS::TraceKind::Object; }
|
||||
bool isScript() const { return kind() == JS::TraceKind::Script; }
|
||||
bool isString() const { return kind() == JS::TraceKind::String; }
|
||||
bool isSymbol() const { return kind() == JS::TraceKind::Symbol; }
|
||||
bool isShape() const { return kind() == JS::TraceKind::Shape; }
|
||||
bool isObjectGroup() const { return kind() == JS::TraceKind::ObjectGroup; }
|
||||
|
||||
// Conversions to more specific types must match the kind. Access to
|
||||
// further refined types is not allowed directly from a GCCellPtr.
|
||||
template <typename T>
|
||||
T& as() const {
|
||||
MOZ_ASSERT(kind() == JS::MapTypeToTraceKind<T>::kind);
|
||||
// We can't use static_cast here, because the fact that JSObject
|
||||
// inherits from js::gc::Cell is not part of the public API.
|
||||
return *reinterpret_cast<T*>(asCell());
|
||||
JSObject* toObject() const {
|
||||
MOZ_ASSERT(kind() == JS::TraceKind::Object);
|
||||
return reinterpret_cast<JSObject*>(asCell());
|
||||
}
|
||||
JSString* toString() const {
|
||||
MOZ_ASSERT(kind() == JS::TraceKind::String);
|
||||
return reinterpret_cast<JSString*>(asCell());
|
||||
}
|
||||
JSScript* toScript() const {
|
||||
MOZ_ASSERT(kind() == JS::TraceKind::Script);
|
||||
return reinterpret_cast<JSScript*>(asCell());
|
||||
}
|
||||
Symbol* toSymbol() const {
|
||||
MOZ_ASSERT(kind() == JS::TraceKind::Symbol);
|
||||
return reinterpret_cast<Symbol*>(asCell());
|
||||
}
|
||||
|
||||
// Return a pointer to the cell this |GCCellPtr| refers to, or |nullptr|.
|
||||
// (It would be more symmetrical with |to| for this to return a |Cell&|, but
|
||||
// the result can be |nullptr|, and null references are undefined behavior.)
|
||||
js::gc::Cell* asCell() const {
|
||||
return reinterpret_cast<js::gc::Cell*>(ptr & ~OutOfLineTraceKindMask);
|
||||
}
|
||||
|
|
|
@ -7,18 +7,6 @@
|
|||
#ifndef js_TraceKind_h
|
||||
#define js_TraceKind_h
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
// Forward declarations of all the types a TraceKind can denote.
|
||||
namespace js {
|
||||
class BaseShape;
|
||||
class LazyScript;
|
||||
class ObjectGroup;
|
||||
namespace jit {
|
||||
class JitCode;
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
namespace JS {
|
||||
|
||||
// When tracing a thing, the GC needs to know about the layout of the object it
|
||||
|
@ -59,82 +47,6 @@ static_assert(uintptr_t(JS::TraceKind::BaseShape) & OutOfLineTraceKindMask, "mas
|
|||
static_assert(uintptr_t(JS::TraceKind::JitCode) & OutOfLineTraceKindMask, "mask bits are set");
|
||||
static_assert(uintptr_t(JS::TraceKind::LazyScript) & OutOfLineTraceKindMask, "mask bits are set");
|
||||
|
||||
#define JS_FOR_EACH_TRACEKIND(D) \
|
||||
/* PrettyName TypeName AddToCCKind */ \
|
||||
D(BaseShape, js::BaseShape, true) \
|
||||
D(JitCode, js::jit::JitCode, true) \
|
||||
D(LazyScript, js::LazyScript, true) \
|
||||
D(Object, JSObject, true) \
|
||||
D(ObjectGroup, js::ObjectGroup, true) \
|
||||
D(Script, JSScript, true) \
|
||||
D(Shape, js::Shape, true) \
|
||||
D(String, JSString, false) \
|
||||
D(Symbol, JS::Symbol, false)
|
||||
|
||||
// Map from base trace type to the trace kind.
|
||||
template <typename T> struct MapTypeToTraceKind {};
|
||||
#define JS_EXPAND_DEF(name, type, _) \
|
||||
template <> struct MapTypeToTraceKind<type> { \
|
||||
static const JS::TraceKind kind = JS::TraceKind::name; \
|
||||
};
|
||||
JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
|
||||
#undef JS_EXPAND_DEF
|
||||
|
||||
// Fortunately, few places in the system need to deal with fully abstract
|
||||
// cells. In those places that do, we generally want to move to a layout
|
||||
// templated function as soon as possible. This template wraps the upcast
|
||||
// for that dispatch.
|
||||
//
|
||||
// Given a call:
|
||||
//
|
||||
// DispatchTraceKindTyped(f, thing, traceKind, ... args)
|
||||
//
|
||||
// Downcast the |void *thing| to the specific type designated by |traceKind|,
|
||||
// and pass it to the functor |f| along with |... args|, forwarded. Pass the
|
||||
// type designated by |traceKind| as the functor's template argument. The
|
||||
// |thing| parameter is optional; without it, we simply pass through |... args|.
|
||||
|
||||
// GCC and Clang require an explicit template declaration in front of the
|
||||
// specialization of operator() because it is a dependent template. MSVC, on
|
||||
// the other hand, gets very confused if we have a |template| token there.
|
||||
#ifdef _MSC_VER
|
||||
# define JS_DEPENDENT_TEMPLATE_HINT
|
||||
#else
|
||||
# define JS_DEPENDENT_TEMPLATE_HINT template
|
||||
#endif
|
||||
template <typename F, typename... Args>
|
||||
auto
|
||||
DispatchTraceKindTyped(F f, JS::TraceKind traceKind, Args&&... args)
|
||||
-> decltype(f. JS_DEPENDENT_TEMPLATE_HINT operator()<JSObject>(mozilla::Forward<Args>(args)...))
|
||||
{
|
||||
switch (traceKind) {
|
||||
#define JS_EXPAND_DEF(name, type, _) \
|
||||
case JS::TraceKind::name: \
|
||||
return f. JS_DEPENDENT_TEMPLATE_HINT operator()<type>(mozilla::Forward<Args>(args)...);
|
||||
JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
|
||||
#undef JS_EXPAND_DEF
|
||||
default:
|
||||
MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped.");
|
||||
}
|
||||
}
|
||||
#undef JS_DEPENDENT_TEMPLATE_HINT
|
||||
|
||||
template <typename F, typename... Args>
|
||||
auto
|
||||
DispatchTraceKindTyped(F f, void* thing, JS::TraceKind traceKind, Args&&... args)
|
||||
-> decltype(f(reinterpret_cast<JSObject*>(0), mozilla::Forward<Args>(args)...))
|
||||
{
|
||||
switch (traceKind) {
|
||||
#define JS_EXPAND_DEF(name, type, _) \
|
||||
case JS::TraceKind::name: \
|
||||
return f(static_cast<type*>(thing), mozilla::Forward<Args>(args)...);
|
||||
JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
|
||||
#undef JS_EXPAND_DEF
|
||||
default:
|
||||
MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif // js_TraceKind_h
|
||||
|
|
|
@ -26,6 +26,15 @@ GCTraceKindToAscii(JS::TraceKind kind);
|
|||
|
||||
} // namespace JS
|
||||
|
||||
namespace js {
|
||||
class BaseShape;
|
||||
class LazyScript;
|
||||
class ObjectGroup;
|
||||
namespace jit {
|
||||
class JitCode;
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
enum WeakMapTraceKind {
|
||||
DoNotTraceWeakMaps = 0,
|
||||
TraceWeakMapValues = 1,
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
using JS::MapTypeToTraceKind;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::IsBaseOf;
|
||||
|
@ -257,7 +255,7 @@ CheckTracedThing<jsid>(JSTracer* trc, jsid id)
|
|||
|
||||
#define IMPL_CHECK_TRACED_THING(_, type, __) \
|
||||
template void CheckTracedThing<type*>(JSTracer*, type*);
|
||||
JS_FOR_EACH_TRACEKIND(IMPL_CHECK_TRACED_THING);
|
||||
FOR_EACH_GC_LAYOUT(IMPL_CHECK_TRACED_THING);
|
||||
#undef IMPL_CHECK_TRACED_THING
|
||||
} // namespace js
|
||||
|
||||
|
@ -406,7 +404,7 @@ template <typename T,
|
|||
struct BaseGCType;
|
||||
#define IMPL_BASE_GC_TYPE(name, type_, _) \
|
||||
template <typename T> struct BaseGCType<T, JS::TraceKind:: name> { typedef type_ type; };
|
||||
JS_FOR_EACH_TRACEKIND(IMPL_BASE_GC_TYPE);
|
||||
FOR_EACH_GC_LAYOUT(IMPL_BASE_GC_TYPE);
|
||||
#undef IMPL_BASE_GC_TYPE
|
||||
|
||||
// Our barrier templates are parameterized on the pointer types so that we can
|
||||
|
@ -556,7 +554,7 @@ js::TraceGenericPointerRoot(JSTracer* trc, Cell** thingp, const char* name)
|
|||
if (!*thingp)
|
||||
return;
|
||||
TraceRootFunctor f;
|
||||
DispatchTraceKindTyped(f, (*thingp)->getTraceKind(), trc, thingp, name);
|
||||
CallTyped(f, (*thingp)->getTraceKind(), trc, thingp, name);
|
||||
}
|
||||
|
||||
// A typed functor adaptor for TraceManuallyBarrieredEdge.
|
||||
|
@ -574,7 +572,7 @@ js::TraceManuallyBarrieredGenericPointerEdge(JSTracer* trc, Cell** thingp, const
|
|||
if (!*thingp)
|
||||
return;
|
||||
TraceManuallyBarrieredEdgeFunctor f;
|
||||
DispatchTraceKindTyped(f, (*thingp)->getTraceKind(), trc, thingp, name);
|
||||
CallTyped(f, (*thingp)->getTraceKind(), trc, thingp, name);
|
||||
}
|
||||
|
||||
// This method is responsible for dynamic dispatch to the real tracer
|
||||
|
@ -586,7 +584,7 @@ DispatchToTracer(JSTracer* trc, T* thingp, const char* name)
|
|||
{
|
||||
#define IS_SAME_TYPE_OR(name, type, _) mozilla::IsSame<type*, T>::value ||
|
||||
static_assert(
|
||||
JS_FOR_EACH_TRACEKIND(IS_SAME_TYPE_OR)
|
||||
FOR_EACH_GC_LAYOUT(IS_SAME_TYPE_OR)
|
||||
mozilla::IsSame<T, JS::Value>::value ||
|
||||
mozilla::IsSame<T, jsid>::value,
|
||||
"Only the base cell layout types are allowed into marking/tracing internals");
|
||||
|
@ -1733,7 +1731,7 @@ struct PushArenaFunctor {
|
|||
void
|
||||
gc::PushArena(GCMarker* gcmarker, ArenaHeader* aheader)
|
||||
{
|
||||
DispatchTraceKindTyped(PushArenaFunctor(), MapAllocToTraceKind(aheader->getAllocKind()), gcmarker, aheader);
|
||||
CallTyped(PushArenaFunctor(), MapAllocToTraceKind(aheader->getAllocKind()), gcmarker, aheader);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -2118,7 +2116,7 @@ CheckIsMarkedThing(T* thingp)
|
|||
{
|
||||
#define IS_SAME_TYPE_OR(name, type, _) mozilla::IsSame<type*, T>::value ||
|
||||
static_assert(
|
||||
JS_FOR_EACH_TRACEKIND(IS_SAME_TYPE_OR)
|
||||
FOR_EACH_GC_LAYOUT(IS_SAME_TYPE_OR)
|
||||
false, "Only the base cell layout types are allowed into marking/tracing internals");
|
||||
#undef IS_SAME_TYPE_OR
|
||||
|
||||
|
|
|
@ -526,7 +526,7 @@ BufferGrayRootsTracer::onChild(const JS::GCCellPtr& thing)
|
|||
// objects and scripts. We rely on gray root buffering for this to work,
|
||||
// but we only need to worry about uncollected dead compartments during
|
||||
// incremental GCs (when we do gray root buffering).
|
||||
DispatchTraceKindTyped(SetMaybeAliveFunctor(), tenured, thing.kind());
|
||||
CallTyped(SetMaybeAliveFunctor(), tenured, thing.kind());
|
||||
|
||||
if (!zone->gcGrayRoots.append(tenured))
|
||||
bufferingGrayRootsFailed = true;
|
||||
|
|
|
@ -53,7 +53,7 @@ DoCallback(JS::CallbackTracer* trc, T* thingp, const char* name)
|
|||
}
|
||||
#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(name, type, _) \
|
||||
template type* DoCallback<type*>(JS::CallbackTracer*, type**, const char*);
|
||||
JS_FOR_EACH_TRACEKIND(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS);
|
||||
FOR_EACH_GC_LAYOUT(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS);
|
||||
#undef INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS
|
||||
|
||||
template <typename S>
|
||||
|
@ -193,7 +193,7 @@ js::TraceChildren(JSTracer* trc, void* thing, JS::TraceKind kind)
|
|||
{
|
||||
MOZ_ASSERT(thing);
|
||||
TraceChildrenFunctor f;
|
||||
DispatchTraceKindTyped(f, kind, trc, thing);
|
||||
CallTyped(f, kind, trc, thing);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
|
@ -331,23 +331,23 @@ struct ObjectGroupCycleCollectorTracer : public JS::CallbackTracer
|
|||
void
|
||||
ObjectGroupCycleCollectorTracer::onChild(const JS::GCCellPtr& thing)
|
||||
{
|
||||
if (thing.is<JSObject>() || thing.is<JSScript>()) {
|
||||
if (thing.isObject() || thing.isScript()) {
|
||||
// Invoke the inner cycle collector callback on this child. It will not
|
||||
// recurse back into TraceChildren.
|
||||
innerTracer->onChild(thing);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing.is<ObjectGroup>()) {
|
||||
if (thing.isObjectGroup()) {
|
||||
// If this group is required to be in an ObjectGroup chain, trace it
|
||||
// via the provided worklist rather than continuing to recurse.
|
||||
ObjectGroup& group = thing.as<ObjectGroup>();
|
||||
if (group.maybeUnboxedLayout()) {
|
||||
ObjectGroup* group = static_cast<ObjectGroup*>(thing.asCell());
|
||||
if (group->maybeUnboxedLayout()) {
|
||||
for (size_t i = 0; i < seen.length(); i++) {
|
||||
if (seen[i] == &group)
|
||||
if (seen[i] == group)
|
||||
return;
|
||||
}
|
||||
if (seen.append(&group) && worklist.append(&group)) {
|
||||
if (seen.append(group) && worklist.append(group)) {
|
||||
return;
|
||||
} else {
|
||||
// If append fails, keep tracing normally. The worst that will
|
||||
|
|
|
@ -205,15 +205,15 @@ JS_WrapPropertyDescriptor(JSContext* cx, JS::MutableHandle<js::PropertyDescripto
|
|||
JS_FRIEND_API(void)
|
||||
JS_TraceShapeCycleCollectorChildren(JS::CallbackTracer* trc, JS::GCCellPtr shape)
|
||||
{
|
||||
MOZ_ASSERT(shape.is<Shape>());
|
||||
TraceCycleCollectorChildren(trc, &shape.as<Shape>());
|
||||
MOZ_ASSERT(shape.isShape());
|
||||
TraceCycleCollectorChildren(trc, static_cast<Shape*>(shape.asCell()));
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS_TraceObjectGroupCycleCollectorChildren(JS::CallbackTracer* trc, JS::GCCellPtr group)
|
||||
{
|
||||
MOZ_ASSERT(group.is<ObjectGroup>());
|
||||
TraceCycleCollectorChildren(trc, &group.as<ObjectGroup>());
|
||||
MOZ_ASSERT(group.isObjectGroup());
|
||||
TraceCycleCollectorChildren(trc, static_cast<ObjectGroup*>(group.asCell()));
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -852,8 +852,8 @@ struct DumpHeapTracer : public JS::CallbackTracer, public WeakMapTracer
|
|||
private:
|
||||
void trace(JSObject* map, JS::GCCellPtr key, JS::GCCellPtr value) override {
|
||||
JSObject* kdelegate = nullptr;
|
||||
if (key.is<JSObject>())
|
||||
kdelegate = js::GetWeakmapKeyDelegate(&key.as<JSObject>());
|
||||
if (key.isObject())
|
||||
kdelegate = js::GetWeakmapKeyDelegate(key.toObject());
|
||||
|
||||
fprintf(output, "WeakMapEntry map=%p key=%p keyDelegate=%p value=%p\n",
|
||||
map, key.asCell(), kdelegate, value.asCell());
|
||||
|
|
|
@ -3721,7 +3721,7 @@ CompartmentCheckTracer::onChild(const JS::GCCellPtr& thing)
|
|||
{
|
||||
TenuredCell* tenured = TenuredCell::fromPointer(thing.asCell());
|
||||
|
||||
JSCompartment* comp = DispatchTraceKindTyped(MaybeCompartmentFunctor(), tenured, thing.kind());
|
||||
JSCompartment* comp = CallTyped(MaybeCompartmentFunctor(), tenured, thing.kind());
|
||||
if (comp && compartment) {
|
||||
MOZ_ASSERT(comp == compartment || runtime()->isAtomsCompartment(comp) ||
|
||||
(srcKind == JS::TraceKind::Object &&
|
||||
|
@ -3744,8 +3744,7 @@ GCRuntime::checkForCompartmentMismatches()
|
|||
for (ZoneCellIterUnderGC i(zone, thingKind); !i.done(); i.next()) {
|
||||
trc.src = i.getCell();
|
||||
trc.srcKind = MapAllocToTraceKind(thingKind);
|
||||
trc.compartment = DispatchTraceKindTyped(MaybeCompartmentFunctor(),
|
||||
trc.src, trc.srcKind);
|
||||
trc.compartment = CallTyped(MaybeCompartmentFunctor(), trc.src, trc.srcKind);
|
||||
JS_TraceChildren(&trc, trc.src, trc.srcKind);
|
||||
}
|
||||
}
|
||||
|
@ -6973,7 +6972,7 @@ JS::GCTraceKindToAscii(JS::TraceKind kind)
|
|||
{
|
||||
switch(kind) {
|
||||
#define MAP_NAME(name, _0, _1) case JS::TraceKind::name: return #name;
|
||||
JS_FOR_EACH_TRACEKIND(MAP_NAME);
|
||||
FOR_EACH_GC_LAYOUT(MAP_NAME);
|
||||
#undef MAP_NAME
|
||||
default: return "Invalid";
|
||||
}
|
||||
|
@ -7003,8 +7002,8 @@ JS::GCCellPtr::outOfLineKind() const
|
|||
bool
|
||||
JS::GCCellPtr::mayBeOwnedByOtherRuntime() const
|
||||
{
|
||||
return (is<JSString>() && as<JSString>().isPermanentAtom()) ||
|
||||
(is<Symbol>() && as<Symbol>().isWellKnownSymbol());
|
||||
return (isString() && toString()->isPermanentAtom()) ||
|
||||
(isSymbol() && toSymbol()->isWellKnownSymbol());
|
||||
}
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
|
@ -7197,7 +7196,7 @@ JS::IncrementalReferenceBarrier(GCCellPtr thing)
|
|||
if (!thing)
|
||||
return;
|
||||
|
||||
DispatchTraceKindTyped(IncrementalReferenceBarrierFunctor(), thing.asCell(), thing.kind());
|
||||
CallTyped(IncrementalReferenceBarrierFunctor(), thing.asCell(), thing.kind());
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
|
|
|
@ -23,6 +23,18 @@
|
|||
|
||||
#include "vm/NativeObject.h"
|
||||
|
||||
#define FOR_EACH_GC_LAYOUT(D) \
|
||||
/* PrettyName TypeName AddToCCKind */ \
|
||||
D(BaseShape, js::BaseShape, true) \
|
||||
D(JitCode, js::jit::JitCode, true) \
|
||||
D(LazyScript, js::LazyScript, true) \
|
||||
D(Object, JSObject, true) \
|
||||
D(ObjectGroup, js::ObjectGroup, true) \
|
||||
D(Script, JSScript, true) \
|
||||
D(Shape, js::Shape, true) \
|
||||
D(String, JSString, false) \
|
||||
D(Symbol, JS::Symbol, false)
|
||||
|
||||
namespace js {
|
||||
|
||||
unsigned GetCPUCount();
|
||||
|
@ -51,6 +63,15 @@ enum State {
|
|||
COMPACT
|
||||
};
|
||||
|
||||
// Map from base trace type to the trace kind.
|
||||
template <typename T> struct MapTypeToTraceKind {};
|
||||
#define EXPAND_DEF(name, type, _) \
|
||||
template <> struct MapTypeToTraceKind<type> { \
|
||||
static const JS::TraceKind kind = JS::TraceKind::name; \
|
||||
};
|
||||
FOR_EACH_GC_LAYOUT(EXPAND_DEF);
|
||||
#undef EXPAND_DEF
|
||||
|
||||
/* Map from C++ type to alloc kind. JSObject does not have a 1:1 mapping, so must use Arena::thingSize. */
|
||||
template <typename T> struct MapTypeToFinalizeKind {};
|
||||
template <> struct MapTypeToFinalizeKind<JSScript> { static const AllocKind kind = AllocKind::SCRIPT; };
|
||||
|
@ -68,7 +89,7 @@ template <> struct MapTypeToFinalizeKind<jit::JitCode> { static const Alloc
|
|||
template <typename T> struct ParticipatesInCC {};
|
||||
#define EXPAND_PARTICIPATES_IN_CC(_, type, addToCCKind) \
|
||||
template <> struct ParticipatesInCC<type> { static const bool value = addToCCKind; };
|
||||
JS_FOR_EACH_TRACEKIND(EXPAND_PARTICIPATES_IN_CC)
|
||||
FOR_EACH_GC_LAYOUT(EXPAND_PARTICIPATES_IN_CC)
|
||||
#undef EXPAND_PARTICIPATES_IN_CC
|
||||
|
||||
static inline bool
|
||||
|
@ -156,6 +177,53 @@ CanBeFinalizedInBackground(AllocKind kind, const Class* clasp)
|
|||
(!clasp->finalize || (clasp->flags & JSCLASS_BACKGROUND_FINALIZE)));
|
||||
}
|
||||
|
||||
// Fortunately, few places in the system need to deal with fully abstract
|
||||
// cells. In those places that do, we generally want to move to a layout
|
||||
// templated function as soon as possible. This template wraps the upcast
|
||||
// for that dispatch.
|
||||
//
|
||||
// Call the functor |F f| with template parameter of the layout type.
|
||||
|
||||
// GCC and Clang require an explicit template declaration in front of the
|
||||
// specialization of operator() because it is a dependent template. MSVC, on
|
||||
// the other hand, gets very confused if we have a |template| token there.
|
||||
#ifdef _MSC_VER
|
||||
# define DEPENDENT_TEMPLATE_HINT
|
||||
#else
|
||||
# define DEPENDENT_TEMPLATE_HINT template
|
||||
#endif
|
||||
template <typename F, typename... Args>
|
||||
auto
|
||||
CallTyped(F f, JS::TraceKind traceKind, Args&&... args)
|
||||
-> decltype(f. DEPENDENT_TEMPLATE_HINT operator()<JSObject>(mozilla::Forward<Args>(args)...))
|
||||
{
|
||||
switch (traceKind) {
|
||||
#define EXPAND_DEF(name, type, _) \
|
||||
case JS::TraceKind::name: \
|
||||
return f. DEPENDENT_TEMPLATE_HINT operator()<type>(mozilla::Forward<Args>(args)...);
|
||||
FOR_EACH_GC_LAYOUT(EXPAND_DEF);
|
||||
#undef EXPAND_DEF
|
||||
default:
|
||||
MOZ_CRASH("Invalid trace kind in CallTyped.");
|
||||
}
|
||||
}
|
||||
#undef DEPENDENT_TEMPLATE_HINT
|
||||
|
||||
template <typename F, typename... Args>
|
||||
auto
|
||||
CallTyped(F f, void* thing, JS::TraceKind traceKind, Args&&... args)
|
||||
-> decltype(f(reinterpret_cast<JSObject*>(0), mozilla::Forward<Args>(args)...))
|
||||
{
|
||||
switch (traceKind) {
|
||||
#define EXPAND_DEF(name, type, _) \
|
||||
case JS::TraceKind::name: \
|
||||
return f(static_cast<type*>(thing), mozilla::Forward<Args>(args)...);
|
||||
FOR_EACH_GC_LAYOUT(EXPAND_DEF);
|
||||
#undef EXPAND_DEF
|
||||
default:
|
||||
MOZ_CRASH("Invalid trace kind in CallTyped.");
|
||||
}
|
||||
}
|
||||
/* Capacity for slotsToThingKind */
|
||||
const size_t SLOTS_TO_THING_KIND_LIMIT = 17;
|
||||
|
||||
|
|
|
@ -251,8 +251,8 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
|
|||
gc::Cell* value = gc::ToMarkable(r.front().value());
|
||||
if (key && value) {
|
||||
tracer->trace(memberOf,
|
||||
JS::GCCellPtr(r.front().key().get()),
|
||||
JS::GCCellPtr(r.front().value().get()));
|
||||
JS::GCCellPtr(r.front().key()),
|
||||
JS::GCCellPtr(r.front().value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
using mozilla::Some;
|
||||
using mozilla::UniquePtr;
|
||||
using JS::DispatchTraceKindTyped;
|
||||
using JS::HandleValue;
|
||||
using JS::Value;
|
||||
using JS::ZoneSet;
|
||||
|
@ -68,7 +67,7 @@ struct Node::ConstructFunctor : public js::BoolDefaultAdaptor<Value, false> {
|
|||
|
||||
Node::Node(const JS::GCCellPtr &thing)
|
||||
{
|
||||
DispatchTraceKindTyped(ConstructFunctor(), thing.asCell(), thing.kind(), this);
|
||||
js::gc::CallTyped(ConstructFunctor(), thing.asCell(), thing.kind(), this);
|
||||
}
|
||||
|
||||
Node::Node(HandleValue value)
|
||||
|
@ -118,9 +117,9 @@ class SimpleEdgeVectorTracer : public JS::CallbackTracer {
|
|||
|
||||
// Don't trace permanent atoms and well-known symbols that are owned by
|
||||
// a parent JSRuntime.
|
||||
if (thing.is<JSString>() && thing.as<JSString>().isPermanentAtom())
|
||||
if (thing.isString() && thing.toString()->isPermanentAtom())
|
||||
return;
|
||||
if (thing.is<JS::Symbol>() && thing.as<JS::Symbol>().isWellKnownSymbol())
|
||||
if (thing.isSymbol() && thing.toSymbol()->isWellKnownSymbol())
|
||||
return;
|
||||
|
||||
char16_t* name16 = nullptr;
|
||||
|
@ -205,7 +204,7 @@ TracerConcrete<Referent>::edges(JSContext* cx, bool wantNames) const {
|
|||
if (!range)
|
||||
return nullptr;
|
||||
|
||||
if (!range->init(cx, ptr, JS::MapTypeToTraceKind<Referent>::kind, wantNames))
|
||||
if (!range->init(cx, ptr, ::js::gc::MapTypeToTraceKind<Referent>::kind, wantNames))
|
||||
return nullptr;
|
||||
|
||||
return UniquePtr<EdgeRange>(range.release());
|
||||
|
|
|
@ -134,7 +134,7 @@ struct NoteWeakMapChildrenTracer : public JS::CallbackTracer
|
|||
void
|
||||
NoteWeakMapChildrenTracer::onChild(const JS::GCCellPtr& aThing)
|
||||
{
|
||||
if (aThing.is<JSString>()) {
|
||||
if (aThing.isString()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ NoteWeakMapsTracer::trace(JSObject* aMap, JS::GCCellPtr aKey,
|
|||
// If nothing that could be held alive by this entry is marked gray, return.
|
||||
if ((!aKey || !JS::GCThingIsMarkedGray(aKey)) &&
|
||||
MOZ_LIKELY(!mCb.WantAllTraces())) {
|
||||
if (!aValue || !JS::GCThingIsMarkedGray(aValue) || aValue.is<JSString>()) {
|
||||
if (!aValue || !JS::GCThingIsMarkedGray(aValue) || aValue.isString()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -188,8 +188,8 @@ NoteWeakMapsTracer::trace(JSObject* aMap, JS::GCCellPtr aKey,
|
|||
}
|
||||
|
||||
JSObject* kdelegate = nullptr;
|
||||
if (aKey.is<JSObject>()) {
|
||||
kdelegate = js::GetWeakmapKeyDelegate(&aKey.as<JSObject>());
|
||||
if (aKey.isObject()) {
|
||||
kdelegate = js::GetWeakmapKeyDelegate(aKey.toObject());
|
||||
}
|
||||
|
||||
if (AddToCCKind(aValue.kind())) {
|
||||
|
@ -200,7 +200,7 @@ NoteWeakMapsTracer::trace(JSObject* aMap, JS::GCCellPtr aKey,
|
|||
mChildTracer.mKey = aKey;
|
||||
mChildTracer.mKeyDelegate = kdelegate;
|
||||
|
||||
if (aValue.is<JSString>()) {
|
||||
if (aValue.isString()) {
|
||||
JS_TraceChildren(&mChildTracer, aValue.asCell(), aValue.kind());
|
||||
}
|
||||
|
||||
|
@ -244,8 +244,8 @@ struct FixWeakMappingGrayBitsTracer : public js::WeakMapTracer
|
|||
aKey = nullptr;
|
||||
}
|
||||
|
||||
if (delegateMightNeedMarking && aKey.is<JSObject>()) {
|
||||
JSObject* kdelegate = js::GetWeakmapKeyDelegate(&aKey.as<JSObject>());
|
||||
if (delegateMightNeedMarking && aKey.isObject()) {
|
||||
JSObject* kdelegate = js::GetWeakmapKeyDelegate(aKey.toObject());
|
||||
if (kdelegate && !JS::ObjectIsMarkedGray(kdelegate)) {
|
||||
if (JS::UnmarkGrayGCThingRecursively(aKey)) {
|
||||
mAnyMarked = true;
|
||||
|
@ -343,21 +343,21 @@ TraversalTracer::onChild(const JS::GCCellPtr& aThing)
|
|||
getTracingEdgeName(buffer, sizeof(buffer));
|
||||
mCb.NoteNextEdgeName(buffer);
|
||||
}
|
||||
if (aThing.is<JSObject>()) {
|
||||
mCb.NoteJSObject(&aThing.as<JSObject>());
|
||||
if (aThing.isObject()) {
|
||||
mCb.NoteJSObject(aThing.toObject());
|
||||
} else {
|
||||
mCb.NoteJSScript(&aThing.as<JSScript>());
|
||||
mCb.NoteJSScript(aThing.toScript());
|
||||
}
|
||||
} else if (aThing.is<js::Shape>()) {
|
||||
} else if (aThing.isShape()) {
|
||||
// The maximum depth of traversal when tracing a Shape is unbounded, due to
|
||||
// the parent pointers on the shape.
|
||||
JS_TraceShapeCycleCollectorChildren(this, aThing);
|
||||
} else if (aThing.is<js::ObjectGroup>()) {
|
||||
} else if (aThing.isObjectGroup()) {
|
||||
// The maximum depth of traversal when tracing an ObjectGroup is unbounded,
|
||||
// due to information attached to the groups which can lead other groups to
|
||||
// be traced.
|
||||
JS_TraceObjectGroupCycleCollectorChildren(this, aThing);
|
||||
} else if (!aThing.is<JSString>()) {
|
||||
} else if (!aThing.isString()) {
|
||||
JS_TraceChildren(this, aThing.asCell(), aThing.kind());
|
||||
}
|
||||
}
|
||||
|
@ -483,8 +483,8 @@ CycleCollectedJSRuntime::DescribeGCThing(bool aIsMarked, JS::GCCellPtr aThing,
|
|||
|
||||
char name[72];
|
||||
uint64_t compartmentAddress = 0;
|
||||
if (aThing.is<JSObject>()) {
|
||||
JSObject* obj = &aThing.as<JSObject>();
|
||||
if (aThing.isObject()) {
|
||||
JSObject* obj = aThing.toObject();
|
||||
compartmentAddress = (uint64_t)js::GetObjectCompartment(obj);
|
||||
const js::Class* clasp = js::GetObjectClass(obj);
|
||||
|
||||
|
@ -582,8 +582,8 @@ CycleCollectedJSRuntime::TraverseGCThing(TraverseSelect aTs, JS::GCCellPtr aThin
|
|||
NoteGCThingJSChildren(aThing, aCb);
|
||||
}
|
||||
|
||||
if (aThing.is<JSObject>()) {
|
||||
JSObject* obj = &aThing.as<JSObject>();
|
||||
if (aThing.isObject()) {
|
||||
JSObject* obj = aThing.toObject();
|
||||
NoteGCThingXPCOMChildren(js::GetObjectClass(obj), obj, aCb);
|
||||
}
|
||||
}
|
||||
|
@ -635,7 +635,7 @@ CycleCollectedJSRuntime::TraverseObjectShim(void* aData, JS::GCCellPtr aThing)
|
|||
TraverseObjectShimClosure* closure =
|
||||
static_cast<TraverseObjectShimClosure*>(aData);
|
||||
|
||||
MOZ_ASSERT(aThing.is<JSObject>());
|
||||
MOZ_ASSERT(aThing.isObject());
|
||||
closure->self->TraverseGCThing(CycleCollectedJSRuntime::TRAVERSE_CPP,
|
||||
aThing, closure->cb);
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@ nsScriptObjectTracer::NoteJSChild(JS::GCCellPtr aGCThing, const char* aName,
|
|||
nsCycleCollectionTraversalCallback* cb =
|
||||
static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, aName);
|
||||
if (aGCThing.is<JSObject>()) {
|
||||
cb->NoteJSObject(&aGCThing.as<JSObject>());
|
||||
} else if (aGCThing.is<JSScript>()) {
|
||||
cb->NoteJSScript(&aGCThing.as<JSScript>());
|
||||
if (aGCThing.isObject()) {
|
||||
cb->NoteJSObject(aGCThing.toObject());
|
||||
} else if (aGCThing.isScript()) {
|
||||
cb->NoteJSScript(aGCThing.toScript());
|
||||
} else {
|
||||
MOZ_ASSERT(!mozilla::AddToCCKind(aGCThing.kind()));
|
||||
}
|
||||
|
@ -97,33 +97,33 @@ void
|
|||
TraceCallbackFunc::Trace(JS::Heap<JSObject*>* aPtr, const char* aName,
|
||||
void* aClosure) const
|
||||
{
|
||||
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
|
||||
mCallback(JS::GCCellPtr(*aPtr), aName, aClosure);
|
||||
}
|
||||
|
||||
void
|
||||
TraceCallbackFunc::Trace(JS::TenuredHeap<JSObject*>* aPtr, const char* aName,
|
||||
void* aClosure) const
|
||||
{
|
||||
mCallback(JS::GCCellPtr(aPtr->getPtr()), aName, aClosure);
|
||||
mCallback(JS::GCCellPtr(*aPtr), aName, aClosure);
|
||||
}
|
||||
|
||||
void
|
||||
TraceCallbackFunc::Trace(JS::Heap<JSFunction*>* aPtr, const char* aName,
|
||||
void* aClosure) const
|
||||
{
|
||||
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
|
||||
mCallback(JS::GCCellPtr(*aPtr), aName, aClosure);
|
||||
}
|
||||
|
||||
void
|
||||
TraceCallbackFunc::Trace(JS::Heap<JSString*>* aPtr, const char* aName,
|
||||
void* aClosure) const
|
||||
{
|
||||
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
|
||||
mCallback(JS::GCCellPtr(*aPtr), aName, aClosure);
|
||||
}
|
||||
|
||||
void
|
||||
TraceCallbackFunc::Trace(JS::Heap<JSScript*>* aPtr, const char* aName,
|
||||
void* aClosure) const
|
||||
{
|
||||
mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
|
||||
mCallback(JS::GCCellPtr(*aPtr), aName, aClosure);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче