JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing, JSGCTraceKind kind, bool details) { const char *name = nullptr; /* silence uninitialized warning */ size_t n; if (bufsize == 0) return; switch (kind) { case JSTRACE_OBJECT: { name = static_cast<JSObject *>(thing)->getClass()->name; break; } case JSTRACE_STRING: name = ((JSString *)thing)->isDependent() ? "substring" : "string"; break; case JSTRACE_SYMBOL: name = "symbol"; break; case JSTRACE_SCRIPT: name = "script"; break; case JSTRACE_LAZY_SCRIPT: name = "lazyscript"; break; case JSTRACE_JITCODE: name = "jitcode"; break; case JSTRACE_SHAPE: name = "shape"; break; case JSTRACE_BASE_SHAPE: name = "base_shape"; break; case JSTRACE_TYPE_OBJECT: name = "type_object"; break; } n = strlen(name); if (n > bufsize - 1) n = bufsize - 1; js_memcpy(buf, name, n + 1); buf += n; bufsize -= n; *buf = '\0'; if (details && bufsize > 2) { switch (kind) { case JSTRACE_OBJECT: { JSObject *obj = (JSObject *)thing; if (obj->is<JSFunction>()) { JSFunction *fun = &obj->as<JSFunction>(); if (fun->displayAtom()) { *buf++ = ' '; bufsize--; PutEscapedString(buf, bufsize, fun->displayAtom(), 0); } } else if (obj->getClass()->flags & JSCLASS_HAS_PRIVATE) { JS_snprintf(buf, bufsize, " %p", obj->getPrivate()); } else { JS_snprintf(buf, bufsize, " <no private>"); } break; } case JSTRACE_STRING: { *buf++ = ' '; bufsize--; JSString *str = (JSString *)thing; if (str->isLinear()) { bool willFit = str->length() + strlen("<length > ") + CountDecimalDigits(str->length()) < bufsize; n = JS_snprintf(buf, bufsize, "<length %d%s> ", (int)str->length(), willFit ? "" : " (truncated)"); buf += n; bufsize -= n; PutEscapedString(buf, bufsize, &str->asLinear(), 0); } else { JS_snprintf(buf, bufsize, "<rope: length %d>", (int)str->length()); } break; } case JSTRACE_SYMBOL: { JS::Symbol *sym = static_cast<JS::Symbol *>(thing); if (JSString *desc = sym->description()) { if (desc->isLinear()) { *buf++ = ' '; bufsize--; PutEscapedString(buf, bufsize, &desc->asLinear(), 0); } else { JS_snprintf(buf, bufsize, "<nonlinear desc>"); } } else { JS_snprintf(buf, bufsize, "<null>"); } 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: break; } } buf[bufsize - 1] = '\0'; }
JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc, void* thing, JS::TraceKind kind, bool details) { const char* name = nullptr; /* silence uninitialized warning */ size_t n; if (bufsize == 0) return; switch (kind) { case JS::TraceKind::Object: { name = static_cast<JSObject*>(thing)->getClass()->name; break; } case JS::TraceKind::Script: name = "script"; break; case JS::TraceKind::String: name = ((JSString*)thing)->isDependent() ? "substring" : "string"; break; case JS::TraceKind::Symbol: name = "symbol"; break; case JS::TraceKind::BaseShape: name = "base_shape"; break; case JS::TraceKind::JitCode: name = "jitcode"; break; case JS::TraceKind::LazyScript: name = "lazyscript"; break; case JS::TraceKind::Shape: name = "shape"; break; case JS::TraceKind::ObjectGroup: name = "object_group"; break; default: name = "INVALID"; break; } n = strlen(name); if (n > bufsize - 1) n = bufsize - 1; js_memcpy(buf, name, n + 1); buf += n; bufsize -= n; *buf = '\0'; if (details && bufsize > 2) { switch (kind) { case JS::TraceKind::Object: { JSObject* obj = (JSObject*)thing; if (obj->is<JSFunction>()) { JSFunction* fun = &obj->as<JSFunction>(); if (fun->displayAtom()) { *buf++ = ' '; bufsize--; PutEscapedString(buf, bufsize, fun->displayAtom(), 0); } } else if (obj->getClass()->flags & JSCLASS_HAS_PRIVATE) { JS_snprintf(buf, bufsize, " %p", obj->as<NativeObject>().getPrivate()); } else { JS_snprintf(buf, bufsize, " <no private>"); } break; } case JS::TraceKind::Script: { JSScript* script = static_cast<JSScript*>(thing); JS_snprintf(buf, bufsize, " %s:%" PRIuSIZE, script->filename(), script->lineno()); break; } case JS::TraceKind::String: { *buf++ = ' '; bufsize--; JSString* str = (JSString*)thing; if (str->isLinear()) { bool willFit = str->length() + strlen("<length > ") + CountDecimalDigits(str->length()) < bufsize; n = JS_snprintf(buf, bufsize, "<length %d%s> ", (int)str->length(), willFit ? "" : " (truncated)"); buf += n; bufsize -= n; PutEscapedString(buf, bufsize, &str->asLinear(), 0); } else { JS_snprintf(buf, bufsize, "<rope: length %d>", (int)str->length()); } break; } case JS::TraceKind::Symbol: { JS::Symbol* sym = static_cast<JS::Symbol*>(thing); if (JSString* desc = sym->description()) { if (desc->isLinear()) { *buf++ = ' '; bufsize--; PutEscapedString(buf, bufsize, &desc->asLinear(), 0); } else { JS_snprintf(buf, bufsize, "<nonlinear desc>"); } } else { JS_snprintf(buf, bufsize, "<null>"); } break; } default: break; } } buf[bufsize - 1] = '\0'; }
JS_PUBLIC_API void JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc, void* thing, JS::TraceKind kind, bool details) { const char* name = nullptr; /* silence uninitialized warning */ size_t n; if (bufsize == 0) { return; } switch (kind) { case JS::TraceKind::BaseShape: name = "base_shape"; break; case JS::TraceKind::JitCode: name = "jitcode"; break; case JS::TraceKind::LazyScript: name = "lazyscript"; break; case JS::TraceKind::Null: name = "null_pointer"; break; case JS::TraceKind::Object: { name = static_cast<JSObject*>(thing)->getClass()->name; break; } case JS::TraceKind::ObjectGroup: name = "object_group"; break; case JS::TraceKind::RegExpShared: name = "reg_exp_shared"; break; case JS::TraceKind::Scope: name = "scope"; break; case JS::TraceKind::Script: name = "script"; break; case JS::TraceKind::Shape: name = "shape"; break; case JS::TraceKind::String: name = ((JSString*)thing)->isDependent() ? "substring" : "string"; break; case JS::TraceKind::Symbol: name = "symbol"; break; #ifdef ENABLE_BIGINT case JS::TraceKind::BigInt: name = "BigInt"; break; #endif default: name = "INVALID"; break; } n = strlen(name); if (n > bufsize - 1) { n = bufsize - 1; } js_memcpy(buf, name, n + 1); buf += n; bufsize -= n; *buf = '\0'; if (details && bufsize > 2) { switch (kind) { case JS::TraceKind::Object: { JSObject* obj = (JSObject*)thing; if (obj->is<JSFunction>()) { JSFunction* fun = &obj->as<JSFunction>(); if (fun->displayAtom()) { *buf++ = ' '; bufsize--; PutEscapedString(buf, bufsize, fun->displayAtom(), 0); } } else if (obj->getClass()->flags & JSCLASS_HAS_PRIVATE) { snprintf(buf, bufsize, " %p", obj->as<NativeObject>().getPrivate()); } else { snprintf(buf, bufsize, " <no private>"); } break; } case JS::TraceKind::Script: { JSScript* script = static_cast<JSScript*>(thing); snprintf(buf, bufsize, " %s:%u", script->filename(), script->lineno()); break; } case JS::TraceKind::LazyScript: { LazyScript* script = static_cast<LazyScript*>(thing); snprintf(buf, bufsize, " %s:%u", script->filename(), script->lineno()); break; } case JS::TraceKind::String: { *buf++ = ' '; bufsize--; JSString* str = (JSString*)thing; if (str->isLinear()) { const char* header = StringKindHeader(str); bool willFit = str->length() + strlen("<length > ") + strlen(header) + CountDecimalDigits(str->length()) < bufsize; n = snprintf(buf, bufsize, "<%slength %zu%s> ", header, str->length(), willFit ? "" : " (truncated)"); buf += n; bufsize -= n; PutEscapedString(buf, bufsize, &str->asLinear(), 0); } else { snprintf(buf, bufsize, "<rope: length %zu>", str->length()); } break; } case JS::TraceKind::Symbol: { JS::Symbol* sym = static_cast<JS::Symbol*>(thing); if (JSString* desc = sym->description()) { if (desc->isLinear()) { *buf++ = ' '; bufsize--; PutEscapedString(buf, bufsize, &desc->asLinear(), 0); } else { snprintf(buf, bufsize, "<nonlinear desc>"); } } else { snprintf(buf, bufsize, "<null>"); } break; } case JS::TraceKind::Scope: { js::Scope* scope = static_cast<js::Scope*>(thing); snprintf(buf, bufsize, " %s", js::ScopeKindString(scope->kind())); break; } default: break; } } buf[bufsize - 1] = '\0'; }