void MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind) { JS_ASSERT(thingp); JS_ASSERT(*thingp); JS_ASSERT(kind == GetGCThingTraceKind(*thingp)); switch (kind) { case JSTRACE_OBJECT: MarkInternal(trc, reinterpret_cast<JSObject **>(thingp)); break; case JSTRACE_STRING: MarkInternal(trc, reinterpret_cast<JSString **>(thingp)); break; case JSTRACE_SCRIPT: MarkInternal(trc, reinterpret_cast<JSScript **>(thingp)); break; 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; #if JS_HAS_XML_SUPPORT case JSTRACE_XML: MarkInternal(trc, reinterpret_cast<JSXML **>(thingp)); break; #endif } }
void MarkInternal(JSTracer *trc, T **thingp) { JS_ASSERT(thingp); T *thing = *thingp; CheckMarkedThing(trc, thing); JSRuntime *rt = trc->runtime; JS_ASSERT_IF(rt->gcCheckCompartment, thing->compartment() == rt->gcCheckCompartment || thing->compartment() == rt->atomsCompartment); /* * Don't mark things outside a compartment if we are in a per-compartment * GC. */ if (!rt->gcCurrentCompartment || thing->compartment() == rt->gcCurrentCompartment) { if (!trc->callback) { PushMarkStack(static_cast<GCMarker *>(trc), thing); } else { trc->callback(trc, (void **)thingp, GetGCThingTraceKind(thing)); } } #ifdef DEBUG trc->debugPrinter = NULL; trc->debugPrintArg = NULL; #endif }
void MarkInternal(JSTracer *trc, T **thingp) { JS_ASSERT(thingp); T *thing = *thingp; CheckMarkedThing(trc, thing); /* * Don't mark things outside a compartment if we are in a per-compartment * GC. */ if (!trc->callback) { if (thing->compartment()->isCollecting()) PushMarkStack(static_cast<GCMarker *>(trc), thing); } else { trc->callback(trc, (void **)thingp, GetGCThingTraceKind(thing)); JS_SET_TRACING_LOCATION(trc, NULL); } #ifdef DEBUG trc->debugPrinter = NULL; trc->debugPrintArg = NULL; #endif }
void MarkGCThingInternal(JSTracer *trc, void **thingp, const char *name) { JS_SET_TRACING_NAME(trc, name); JS_ASSERT(thingp); if (!*thingp) return; MarkKind(trc, thingp, GetGCThingTraceKind(*thingp)); }
void MarkGCThingRoot(JSTracer *trc, void *thing, const char *name) { JS_ROOT_MARKING_ASSERT(trc); JS_SET_TRACING_NAME(trc, name); if (!thing) return; MarkKind(trc, thing, GetGCThingTraceKind(thing)); }
/* * The function tries to scan the whole rope tree using the marking stack as * temporary storage. If that becomes full, the unscanned ropes are added to * the delayed marking list. When the function returns, the marking stack is * at the same depth as it was on entry. This way we avoid using tags when * pushing ropes to the stack as ropes never leaks to other users of the * stack. This also assumes that a rope can only point to other ropes or * linear strings, it cannot refer to GC things of other types. */ static void ScanRope(GCMarker *gcmarker, JSRope *rope) { ptrdiff_t savedPos = gcmarker->stack.position(); for (;;) { JS_ASSERT(GetGCThingTraceKind(rope) == JSTRACE_STRING); JS_ASSERT(rope->JSString::isRope()); JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime, rope); JS_ASSERT(rope->isMarked()); JSRope *next = NULL; JSString *right = rope->rightChild(); if (right->markIfUnmarked()) { if (right->isLinear()) ScanLinearString(gcmarker, &right->asLinear()); else next = &right->asRope(); } JSString *left = rope->leftChild(); if (left->markIfUnmarked()) { if (left->isLinear()) { ScanLinearString(gcmarker, &left->asLinear()); } else { /* * When both children are ropes, set aside the right one to * scan it later. */ if (next && !gcmarker->stack.push(reinterpret_cast<uintptr_t>(next))) gcmarker->delayMarkingChildren(next); next = &left->asRope(); } } if (next) { rope = next; } else if (savedPos != gcmarker->stack.position()) { JS_ASSERT(savedPos < gcmarker->stack.position()); rope = reinterpret_cast<JSRope *>(gcmarker->stack.pop()); } else { break; } } JS_ASSERT(savedPos == gcmarker->stack.position()); }
void GCMarker::dumpConservativeRoots() { if (!conservativeDumpFileName) return; FILE *fp; if (!strcmp(conservativeDumpFileName, "stdout")) { fp = stdout; } else if (!strcmp(conservativeDumpFileName, "stderr")) { fp = stderr; } else if (!(fp = fopen(conservativeDumpFileName, "aw"))) { fprintf(stderr, "Warning: cannot open %s to dump the conservative roots\n", conservativeDumpFileName); return; } conservativeStats.dump(fp); for (void **thingp = conservativeRoots.begin(); thingp != conservativeRoots.end(); ++thingp) { void *thing = thingp; fprintf(fp, " %p: ", thing); switch (GetGCThingTraceKind(thing)) { default: JS_NOT_REACHED("Unknown trace kind"); case JSTRACE_OBJECT: { JSObject *obj = (JSObject *) thing; fprintf(fp, "object %s", obj->getClass()->name); break; } case JSTRACE_SHAPE: { fprintf(fp, "shape"); break; } case JSTRACE_STRING: { JSString *str = (JSString *) thing; if (str->isLinear()) { char buf[50]; PutEscapedString(buf, sizeof buf, &str->asLinear(), '"'); fprintf(fp, "string %s", buf); } else { fprintf(fp, "rope: length %d", (int)str->length()); } break; } # if JS_HAS_XML_SUPPORT case JSTRACE_XML: { JSXML *xml = (JSXML *) thing; fprintf(fp, "xml %u", (unsigned)xml->xml_class); break; } # endif } fputc('\n', fp); } fputc('\n', fp); if (fp != stdout && fp != stderr) fclose(fp); }