mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 00:08:39 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
243
js/src/gc/GCTrace.cpp
Normal file
243
js/src/gc/GCTrace.cpp
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifdef JS_GC_TRACE
|
||||
|
||||
#include "gc/GCTrace.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gc/GCTraceFormat.h"
|
||||
|
||||
#include "js/HashTable.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
JS_STATIC_ASSERT(AllocKinds == unsigned(AllocKind::LIMIT));
|
||||
JS_STATIC_ASSERT(LastObjectAllocKind == unsigned(AllocKind::OBJECT_LAST));
|
||||
|
||||
static FILE* gcTraceFile = nullptr;
|
||||
|
||||
static HashSet<const Class*, DefaultHasher<const Class*>, SystemAllocPolicy> tracedClasses;
|
||||
static HashSet<const ObjectGroup*, DefaultHasher<const ObjectGroup*>, SystemAllocPolicy> tracedGroups;
|
||||
|
||||
static inline void
|
||||
WriteWord(uint64_t data)
|
||||
{
|
||||
if (gcTraceFile)
|
||||
fwrite(&data, sizeof(data), 1, gcTraceFile);
|
||||
}
|
||||
|
||||
static inline void
|
||||
TraceEvent(GCTraceEvent event, uint64_t payload = 0, uint8_t extra = 0)
|
||||
{
|
||||
MOZ_ASSERT(event < GCTraceEventCount);
|
||||
MOZ_ASSERT((payload >> TracePayloadBits) == 0);
|
||||
WriteWord((uint64_t(event) << TraceEventShift) |
|
||||
(uint64_t(extra) << TraceExtraShift) | payload);
|
||||
}
|
||||
|
||||
static inline void
|
||||
TraceAddress(const void* p)
|
||||
{
|
||||
TraceEvent(TraceDataAddress, uint64_t(p));
|
||||
}
|
||||
|
||||
static inline void
|
||||
TraceInt(uint32_t data)
|
||||
{
|
||||
TraceEvent(TraceDataInt, data);
|
||||
}
|
||||
|
||||
static void
|
||||
TraceString(const char* string)
|
||||
{
|
||||
JS_STATIC_ASSERT(sizeof(char) == 1);
|
||||
|
||||
size_t length = strlen(string);
|
||||
const unsigned charsPerWord = sizeof(uint64_t);
|
||||
unsigned wordCount = (length + charsPerWord - 1) / charsPerWord;
|
||||
|
||||
TraceEvent(TraceDataString, length);
|
||||
for (unsigned i = 0; i < wordCount; ++i) {
|
||||
union
|
||||
{
|
||||
uint64_t word;
|
||||
char chars[charsPerWord];
|
||||
} data;
|
||||
strncpy(data.chars, string + (i * charsPerWord), charsPerWord);
|
||||
WriteWord(data.word);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
js::gc::InitTrace(GCRuntime& gc)
|
||||
{
|
||||
/* This currently does not support multiple runtimes. */
|
||||
MOZ_ALWAYS_TRUE(!gcTraceFile);
|
||||
|
||||
char* filename = getenv("JS_GC_TRACE");
|
||||
if (!filename)
|
||||
return true;
|
||||
|
||||
if (!tracedClasses.init() || !tracedTypes.init()) {
|
||||
FinishTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
gcTraceFile = fopen(filename, "w");
|
||||
if (!gcTraceFile) {
|
||||
FinishTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
TraceEvent(TraceEventInit, 0, TraceFormatVersion);
|
||||
|
||||
/* Trace information about thing sizes. */
|
||||
for (auto kind : AllAllocKinds())
|
||||
TraceEvent(TraceEventThingSize, Arena::thingSize(kind));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::FinishTrace()
|
||||
{
|
||||
if (gcTraceFile) {
|
||||
fclose(gcTraceFile);
|
||||
gcTraceFile = nullptr;
|
||||
}
|
||||
tracedClasses.finish();
|
||||
tracedTypes.finish();
|
||||
}
|
||||
|
||||
bool
|
||||
js::gc::TraceEnabled()
|
||||
{
|
||||
return gcTraceFile != nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::TraceNurseryAlloc(Cell* thing, size_t size)
|
||||
{
|
||||
if (thing) {
|
||||
/* We don't have AllocKind here, but we can work it out from size. */
|
||||
unsigned slots = (size - sizeof(JSObject)) / sizeof(JS::Value);
|
||||
AllocKind kind = GetBackgroundAllocKind(GetGCObjectKind(slots));
|
||||
TraceEvent(TraceEventNurseryAlloc, uint64_t(thing), kind);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::TraceTenuredAlloc(Cell* thing, AllocKind kind)
|
||||
{
|
||||
if (thing)
|
||||
TraceEvent(TraceEventTenuredAlloc, uint64_t(thing), kind);
|
||||
}
|
||||
|
||||
static void
|
||||
MaybeTraceClass(const Class* clasp)
|
||||
{
|
||||
if (tracedClasses.has(clasp))
|
||||
return;
|
||||
|
||||
TraceEvent(TraceEventClassInfo, uint64_t(clasp));
|
||||
TraceString(clasp->name);
|
||||
TraceInt(clasp->flags);
|
||||
TraceInt(clasp->finalize != nullptr);
|
||||
|
||||
MOZ_ALWAYS_TRUE(tracedClasses.put(clasp));
|
||||
}
|
||||
|
||||
static void
|
||||
MaybeTraceGroup(ObjectGroup* group)
|
||||
{
|
||||
if (tracedGroups.has(group))
|
||||
return;
|
||||
|
||||
MaybeTraceClass(group->clasp());
|
||||
TraceEvent(TraceEventGroupInfo, uint64_t(group));
|
||||
TraceAddress(group->clasp());
|
||||
TraceInt(group->flags());
|
||||
|
||||
MOZ_ALWAYS_TRUE(tracedGroups.put(group));
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::TraceTypeNewScript(ObjectGroup* group)
|
||||
{
|
||||
const size_t bufLength = 128;
|
||||
static char buffer[bufLength];
|
||||
MOZ_ASSERT(group->hasNewScript());
|
||||
JSAtom* funName = group->newScript()->fun->displayAtom();
|
||||
if (!funName)
|
||||
return;
|
||||
|
||||
size_t length = funName->length();
|
||||
MOZ_ALWAYS_TRUE(length < bufLength);
|
||||
CopyChars(reinterpret_cast<Latin1Char*>(buffer), *funName);
|
||||
buffer[length] = 0;
|
||||
|
||||
TraceEvent(TraceEventTypeNewScript, uint64_t(group));
|
||||
TraceString(buffer);
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::TraceCreateObject(JSObject* object)
|
||||
{
|
||||
if (!gcTraceFile)
|
||||
return;
|
||||
|
||||
ObjectGroup* group = object->group();
|
||||
MaybeTraceGroup(group);
|
||||
TraceEvent(TraceEventCreateObject, uint64_t(object));
|
||||
TraceAddress(group);
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::TraceMinorGCStart()
|
||||
{
|
||||
TraceEvent(TraceEventMinorGCStart);
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::TracePromoteToTenured(Cell* src, Cell* dst)
|
||||
{
|
||||
TraceEvent(TraceEventPromoteToTenured, uint64_t(src));
|
||||
TraceAddress(dst);
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::TraceMinorGCEnd()
|
||||
{
|
||||
TraceEvent(TraceEventMinorGCEnd);
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::TraceMajorGCStart()
|
||||
{
|
||||
TraceEvent(TraceEventMajorGCStart);
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::TraceTenuredFinalize(Cell* thing)
|
||||
{
|
||||
if (!gcTraceFile)
|
||||
return;
|
||||
if (thing->tenuredGetAllocKind() == AllocKind::OBJECT_GROUP)
|
||||
tracedGroups.remove(static_cast<const ObjectGroup*>(thing));
|
||||
TraceEvent(TraceEventTenuredFinalize, uint64_t(thing));
|
||||
}
|
||||
|
||||
void
|
||||
js::gc::TraceMajorGCEnd()
|
||||
{
|
||||
TraceEvent(TraceEventMajorGCEnd);
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue