Bug 1105069 - Part 1: Move GCTraceKind from jspubtd to TraceAPI; r=jonco, r=mccr8

--HG--
extra : rebase_source : 86fef608628fe2eaa6c6f91e84d90aa9e9baa84d
This commit is contained in:
Terrence Cole 2014-12-01 14:49:07 -08:00
parent e0889ac043
commit 98a5f959aa
10 changed files with 196 additions and 182 deletions

View File

@ -11,6 +11,7 @@
#include "jspubtd.h"
#include "js/TracingAPI.h"
#include "js/Utility.h"
/* These values are private to the JS engine. */

View File

@ -10,7 +10,6 @@
#include "mozilla/NullPtr.h"
#include "jsalloc.h"
#include "jspubtd.h"
#include "js/HashTable.h"
@ -21,6 +20,49 @@ template <typename T> class Heap;
template <typename T> class TenuredHeap;
}
// When tracing a thing, the GC needs to know about the layout of the object it
// is looking at. There are a fixed number of different layouts that the GC
// knows about. The "trace kind" is a static map which tells which layout a GC
// thing has.
//
// Although this map is public, the details are completely hidden. Not all of
// the matching C++ types are exposed, and those that are, are opaque.
//
// See Value::gcKind() and JSTraceCallback in Tracer.h for more details.
enum JSGCTraceKind
{
// These trace kinds have a publicly exposed, although opaque, C++ type.
// Note: The order here is determined by our Value packing. Other users
// should sort alphabetically, for consistency.
JSTRACE_OBJECT = 0x00,
JSTRACE_STRING = 0x01,
JSTRACE_SYMBOL = 0x02,
JSTRACE_SCRIPT = 0x03,
// Shape details are exposed through JS_TraceShapeCycleCollectorChildren.
JSTRACE_SHAPE = 0x04,
// The kind associated with a nullptr.
JSTRACE_NULL = 0x06,
// A kind that indicates the real kind should be looked up in the arena.
JSTRACE_OUTOFLINE = 0x07,
// The following kinds do not have an exposed C++ idiom.
JSTRACE_BASE_SHAPE = 0x0F,
JSTRACE_JITCODE = 0x1F,
JSTRACE_LAZY_SCRIPT = 0x2F,
JSTRACE_TYPE_OBJECT = 0x3F,
JSTRACE_LAST = JSTRACE_TYPE_OBJECT
};
namespace JS {
// Returns a static string equivalent of |kind|.
JS_FRIEND_API(const char *)
GCTraceKindToAscii(JSGCTraceKind kind);
}
// Tracer callback, called for each traceable thing directly referenced by a
// particular object or runtime structure. It is the callback responsibility
// to ensure the traversal of the full object graph via calling eventually

View File

@ -689,14 +689,20 @@ gc::MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind)
case JSTRACE_OBJECT:
MarkInternal(trc, reinterpret_cast<JSObject **>(thingp));
break;
case JSTRACE_SCRIPT:
MarkInternal(trc, reinterpret_cast<JSScript **>(thingp));
break;
case JSTRACE_STRING:
MarkInternal(trc, reinterpret_cast<JSString **>(thingp));
break;
case JSTRACE_SYMBOL:
MarkInternal(trc, reinterpret_cast<JS::Symbol **>(thingp));
break;
case JSTRACE_SCRIPT:
MarkInternal(trc, reinterpret_cast<JSScript **>(thingp));
case JSTRACE_BASE_SHAPE:
MarkInternal(trc, reinterpret_cast<BaseShape **>(thingp));
break;
case JSTRACE_JITCODE:
MarkInternal(trc, reinterpret_cast<jit::JitCode **>(thingp));
break;
case JSTRACE_LAZY_SCRIPT:
MarkInternal(trc, reinterpret_cast<LazyScript **>(thingp));
@ -704,15 +710,11 @@ gc::MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind)
case JSTRACE_SHAPE:
MarkInternal(trc, reinterpret_cast<Shape **>(thingp));
break;
case JSTRACE_BASE_SHAPE:
MarkInternal(trc, reinterpret_cast<BaseShape **>(thingp));
break;
case JSTRACE_TYPE_OBJECT:
MarkInternal(trc, reinterpret_cast<types::TypeObject **>(thingp));
break;
case JSTRACE_JITCODE:
MarkInternal(trc, reinterpret_cast<jit::JitCode **>(thingp));
break;
default:
MOZ_CRASH("Invalid trace kind in MarkKind.");
}
}
@ -1542,6 +1544,10 @@ gc::PushArena(GCMarker *gcmarker, ArenaHeader *aheader)
PushArenaTyped<JSObject>(gcmarker, aheader);
break;
case JSTRACE_SCRIPT:
PushArenaTyped<JSScript>(gcmarker, aheader);
break;
case JSTRACE_STRING:
PushArenaTyped<JSString>(gcmarker, aheader);
break;
@ -1550,8 +1556,12 @@ gc::PushArena(GCMarker *gcmarker, ArenaHeader *aheader)
PushArenaTyped<JS::Symbol>(gcmarker, aheader);
break;
case JSTRACE_SCRIPT:
PushArenaTyped<JSScript>(gcmarker, aheader);
case JSTRACE_BASE_SHAPE:
PushArenaTyped<js::BaseShape>(gcmarker, aheader);
break;
case JSTRACE_JITCODE:
PushArenaTyped<js::jit::JitCode>(gcmarker, aheader);
break;
case JSTRACE_LAZY_SCRIPT:
@ -1562,17 +1572,12 @@ gc::PushArena(GCMarker *gcmarker, ArenaHeader *aheader)
PushArenaTyped<js::Shape>(gcmarker, aheader);
break;
case JSTRACE_BASE_SHAPE:
PushArenaTyped<js::BaseShape>(gcmarker, aheader);
break;
case JSTRACE_TYPE_OBJECT:
PushArenaTyped<js::types::TypeObject>(gcmarker, aheader);
break;
case JSTRACE_JITCODE:
PushArenaTyped<js::jit::JitCode>(gcmarker, aheader);
break;
default:
MOZ_CRASH("Invalid trace kind in PushArena.");
}
}
@ -1946,6 +1951,10 @@ js::TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
MarkChildren(trc, static_cast<JSObject *>(thing));
break;
case JSTRACE_SCRIPT:
MarkChildren(trc, static_cast<JSScript *>(thing));
break;
case JSTRACE_STRING:
MarkChildren(trc, static_cast<JSString *>(thing));
break;
@ -1954,8 +1963,12 @@ js::TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
MarkChildren(trc, static_cast<JS::Symbol *>(thing));
break;
case JSTRACE_SCRIPT:
MarkChildren(trc, static_cast<JSScript *>(thing));
case JSTRACE_BASE_SHAPE:
MarkChildren(trc, static_cast<BaseShape *>(thing));
break;
case JSTRACE_JITCODE:
MarkChildren(trc, (js::jit::JitCode *)thing);
break;
case JSTRACE_LAZY_SCRIPT:
@ -1966,17 +1979,12 @@ js::TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
MarkChildren(trc, static_cast<Shape *>(thing));
break;
case JSTRACE_JITCODE:
MarkChildren(trc, (js::jit::JitCode *)thing);
break;
case JSTRACE_BASE_SHAPE:
MarkChildren(trc, static_cast<BaseShape *>(thing));
break;
case JSTRACE_TYPE_OBJECT:
MarkChildren(trc, (types::TypeObject *)thing);
break;
default:
MOZ_CRASH("Invalid trace kind in TraceChildren.");
}
}

View File

@ -203,6 +203,10 @@ JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
break;
}
case JSTRACE_SCRIPT:
name = "script";
break;
case JSTRACE_STRING:
name = ((JSString *)thing)->isDependent()
? "substring"
@ -213,29 +217,29 @@ JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
name = "symbol";
break;
case JSTRACE_SCRIPT:
name = "script";
break;
case JSTRACE_LAZY_SCRIPT:
name = "lazyscript";
case JSTRACE_BASE_SHAPE:
name = "base_shape";
break;
case JSTRACE_JITCODE:
name = "jitcode";
break;
case JSTRACE_LAZY_SCRIPT:
name = "lazyscript";
break;
case JSTRACE_SHAPE:
name = "shape";
break;
case JSTRACE_BASE_SHAPE:
name = "base_shape";
break;
case JSTRACE_TYPE_OBJECT:
name = "type_object";
break;
default:
name = "INVALID";
break;
}
n = strlen(name);
@ -266,6 +270,13 @@ JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
break;
}
case JSTRACE_SCRIPT:
{
JSScript *script = static_cast<JSScript *>(thing);
JS_snprintf(buf, bufsize, " %s:%u", script->filename(), unsigned(script->lineno()));
break;
}
case JSTRACE_STRING:
{
*buf++ = ' ';
@ -306,18 +317,7 @@ JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
break;
}
case JSTRACE_SCRIPT:
{
JSScript *script = static_cast<JSScript *>(thing);
JS_snprintf(buf, bufsize, " %s:%u", script->filename(), unsigned(script->lineno()));
break;
}
case JSTRACE_LAZY_SCRIPT:
case JSTRACE_JITCODE:
case JSTRACE_SHAPE:
case JSTRACE_BASE_SHAPE:
case JSTRACE_TYPE_OBJECT:
default:
break;
}
}

View File

@ -328,23 +328,6 @@ const uint32_t Arena::FirstThingOffsets[] = {
#undef OFFSET
const char *
js::gc::TraceKindAsAscii(JSGCTraceKind kind)
{
switch(kind) {
case JSTRACE_OBJECT: return "JSTRACE_OBJECT";
case JSTRACE_STRING: return "JSTRACE_STRING";
case JSTRACE_SYMBOL: return "JSTRACE_SYMBOL";
case JSTRACE_SCRIPT: return "JSTRACE_SCRIPT";
case JSTRACE_LAZY_SCRIPT: return "JSTRACE_SCRIPT";
case JSTRACE_JITCODE: return "JSTRACE_JITCODE";
case JSTRACE_SHAPE: return "JSTRACE_SHAPE";
case JSTRACE_BASE_SHAPE: return "JSTRACE_BASE_SHAPE";
case JSTRACE_TYPE_OBJECT: return "JSTRACE_TYPE_OBJECT";
default: return "INVALID";
}
}
struct js::gc::FinalizePhase
{
size_t length;
@ -7046,6 +7029,23 @@ JS::AutoAssertGCCallback::AutoAssertGCCallback(JSObject *obj)
MOZ_ASSERT(obj->runtimeFromMainThread()->isHeapMajorCollecting());
}
JS_FRIEND_API(const char *)
JS::GCTraceKindToAscii(JSGCTraceKind kind)
{
switch(kind) {
case JSTRACE_OBJECT: return "Object";
case JSTRACE_SCRIPT: return "Script";
case JSTRACE_STRING: return "String";
case JSTRACE_SYMBOL: return "Symbol";
case JSTRACE_SHAPE: return "Shape";
case JSTRACE_BASE_SHAPE: return "BaseShape";
case JSTRACE_LAZY_SCRIPT: return "LazyScript";
case JSTRACE_JITCODE: return "JitCode";
case JSTRACE_TYPE_OBJECT: return "TypeObject";
default: return "Invalid";
}
}
#ifdef JSGC_HASH_TABLE_CHECKS
void
js::gc::CheckHashTablesAfterMovingGC(JSRuntime *rt)

View File

@ -61,10 +61,6 @@ enum State {
COMPACT
};
/* Return a printable string for the given kind, for diagnostic purposes. */
const char *
TraceKindAsAscii(JSGCTraceKind kind);
/* 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 = FINALIZE_SCRIPT; };

View File

@ -102,25 +102,6 @@ enum JSIterateOp {
JSENUMERATE_DESTROY
};
/* See Value::gcKind() and JSTraceCallback in Tracer.h. */
enum JSGCTraceKind {
JSTRACE_OBJECT,
JSTRACE_STRING,
JSTRACE_SYMBOL,
JSTRACE_SCRIPT,
/*
* Trace kinds internal to the engine. The embedding can only see them if
* it implements JSTraceCallback.
*/
JSTRACE_LAZY_SCRIPT,
JSTRACE_JITCODE,
JSTRACE_SHAPE,
JSTRACE_BASE_SHAPE,
JSTRACE_TYPE_OBJECT,
JSTRACE_LAST = JSTRACE_TYPE_OBJECT
};
/* Struct forward declarations. */
struct JSClass;
struct JSCompartment;

View File

@ -428,74 +428,6 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
break;
}
case JSTRACE_STRING: {
JSString *str = static_cast<JSString *>(thing);
JS::StringInfo info;
if (str->hasLatin1Chars()) {
info.gcHeapLatin1 = thingSize;
info.mallocHeapLatin1 = str->sizeOfExcludingThis(rtStats->mallocSizeOf_);
} else {
info.gcHeapTwoByte = thingSize;
info.mallocHeapTwoByte = str->sizeOfExcludingThis(rtStats->mallocSizeOf_);
}
info.numCopies = 1;
zStats->stringInfo.add(info);
// The primary use case for anonymization is automated crash submission
// (to help detect OOM crashes). In that case, we don't want to pay the
// memory cost required to do notable string detection.
if (granularity == FineGrained && !closure->anonymize) {
ZoneStats::StringsHashMap::AddPtr p = zStats->allStrings->lookupForAdd(str);
if (!p) {
// Ignore failure -- we just won't record the string as notable.
(void)zStats->allStrings->add(p, str, info);
} else {
p->value().add(info);
}
}
break;
}
case JSTRACE_SYMBOL:
zStats->symbolsGCHeap += thingSize;
break;
case JSTRACE_SHAPE: {
Shape *shape = static_cast<Shape *>(thing);
CompartmentStats *cStats = GetCompartmentStats(shape->compartment());
JS::ClassInfo info; // This zeroes all the sizes.
if (shape->inDictionary())
info.shapesGCHeapDict += thingSize;
else
info.shapesGCHeapTree += thingSize;
shape->addSizeOfExcludingThis(rtStats->mallocSizeOf_, &info);
cStats->classInfo.add(info);
const BaseShape *base = shape->base();
const Class *clasp = base->clasp();
const char *className = clasp->name;
AddClassInfo(granularity, cStats, className, info);
break;
}
case JSTRACE_BASE_SHAPE: {
BaseShape *base = static_cast<BaseShape *>(thing);
CompartmentStats *cStats = GetCompartmentStats(base->compartment());
JS::ClassInfo info; // This zeroes all the sizes.
info.shapesGCHeapBase += thingSize;
// No malloc-heap measurements.
cStats->classInfo.add(info);
const Class *clasp = base->clasp();
const char *className = clasp->name;
AddClassInfo(granularity, cStats, className, info);
break;
}
case JSTRACE_SCRIPT: {
JSScript *script = static_cast<JSScript *>(thing);
CompartmentStats *cStats = GetCompartmentStats(script->compartment());
@ -536,6 +468,62 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
break;
}
case JSTRACE_STRING: {
JSString *str = static_cast<JSString *>(thing);
JS::StringInfo info;
if (str->hasLatin1Chars()) {
info.gcHeapLatin1 = thingSize;
info.mallocHeapLatin1 = str->sizeOfExcludingThis(rtStats->mallocSizeOf_);
} else {
info.gcHeapTwoByte = thingSize;
info.mallocHeapTwoByte = str->sizeOfExcludingThis(rtStats->mallocSizeOf_);
}
info.numCopies = 1;
zStats->stringInfo.add(info);
// The primary use case for anonymization is automated crash submission
// (to help detect OOM crashes). In that case, we don't want to pay the
// memory cost required to do notable string detection.
if (granularity == FineGrained && !closure->anonymize) {
ZoneStats::StringsHashMap::AddPtr p = zStats->allStrings->lookupForAdd(str);
if (!p) {
// Ignore failure -- we just won't record the string as notable.
(void)zStats->allStrings->add(p, str, info);
} else {
p->value().add(info);
}
}
break;
}
case JSTRACE_SYMBOL:
zStats->symbolsGCHeap += thingSize;
break;
case JSTRACE_BASE_SHAPE: {
BaseShape *base = static_cast<BaseShape *>(thing);
CompartmentStats *cStats = GetCompartmentStats(base->compartment());
JS::ClassInfo info; // This zeroes all the sizes.
info.shapesGCHeapBase += thingSize;
// No malloc-heap measurements.
cStats->classInfo.add(info);
const Class *clasp = base->clasp();
const char *className = clasp->name;
AddClassInfo(granularity, cStats, className, info);
break;
}
case JSTRACE_JITCODE: {
zStats->jitCodesGCHeap += thingSize;
// The code for a script is counted in ExecutableAllocator::sizeOfCode().
break;
}
case JSTRACE_LAZY_SCRIPT: {
LazyScript *lazy = static_cast<LazyScript *>(thing);
zStats->lazyScriptsGCHeap += thingSize;
@ -543,9 +531,21 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
break;
}
case JSTRACE_JITCODE: {
zStats->jitCodesGCHeap += thingSize;
// The code for a script is counted in ExecutableAllocator::sizeOfCode().
case JSTRACE_SHAPE: {
Shape *shape = static_cast<Shape *>(thing);
CompartmentStats *cStats = GetCompartmentStats(shape->compartment());
JS::ClassInfo info; // This zeroes all the sizes.
if (shape->inDictionary())
info.shapesGCHeapDict += thingSize;
else
info.shapesGCHeapTree += thingSize;
shape->addSizeOfExcludingThis(rtStats->mallocSizeOf_, &info);
cStats->classInfo.add(info);
const BaseShape *base = shape->base();
const Class *clasp = base->clasp();
const char *className = clasp->name;
AddClassInfo(granularity, cStats, className, info);
break;
}
@ -557,7 +557,7 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
}
default:
MOZ_CRASH("invalid traceKind");
MOZ_CRASH("invalid traceKind in StatsCellCallback");
}
// Yes, this is a subtraction: see StatsArenaCallback() for details.

View File

@ -59,13 +59,13 @@ Node::Node(JSGCTraceKind kind, void *ptr)
{
switch (kind) {
case JSTRACE_OBJECT: construct(static_cast<JSObject *>(ptr)); break;
case JSTRACE_SCRIPT: construct(static_cast<JSScript *>(ptr)); break;
case JSTRACE_STRING: construct(static_cast<JSString *>(ptr)); break;
case JSTRACE_SYMBOL: construct(static_cast<JS::Symbol *>(ptr)); break;
case JSTRACE_SCRIPT: construct(static_cast<JSScript *>(ptr)); break;
case JSTRACE_LAZY_SCRIPT: construct(static_cast<js::LazyScript *>(ptr)); break;
case JSTRACE_JITCODE: construct(static_cast<js::jit::JitCode *>(ptr)); break;
case JSTRACE_SHAPE: construct(static_cast<js::Shape *>(ptr)); break;
case JSTRACE_BASE_SHAPE: construct(static_cast<js::BaseShape *>(ptr)); break;
case JSTRACE_JITCODE: construct(static_cast<js::jit::JitCode *>(ptr)); break;
case JSTRACE_LAZY_SCRIPT: construct(static_cast<js::LazyScript *>(ptr)); break;
case JSTRACE_SHAPE: construct(static_cast<js::Shape *>(ptr)); break;
case JSTRACE_TYPE_OBJECT: construct(static_cast<js::types::TypeObject *>(ptr)); break;
default:

View File

@ -582,24 +582,10 @@ CycleCollectedJSRuntime::DescribeGCThing(bool aIsMarked, void* aThing,
JS_snprintf(name, sizeof(name), "JS Object (Function)");
}
} else {
JS_snprintf(name, sizeof(name), "JS Object (%s)",
clasp->name);
JS_snprintf(name, sizeof(name), "JS Object (%s)", clasp->name);
}
} else {
static const char trace_types[][11] = {
"Object",
"String",
"Symbol",
"Script",
"LazyScript",
"IonCode",
"Shape",
"BaseShape",
"TypeObject",
};
static_assert(MOZ_ARRAY_LENGTH(trace_types) == JSTRACE_LAST + 1,
"JSTRACE_LAST enum must match trace_types count.");
JS_snprintf(name, sizeof(name), "JS %s", trace_types[aTraceKind]);
JS_snprintf(name, sizeof(name), "JS %s", JS::GCTraceKindToAscii(aTraceKind));
}
// Disable printing global for objects while we figure out ObjShrink fallout.