Fix memory leak, improve memory logging. (#2469)

This commit is contained in:
Nikolay Igotti
2018-12-18 14:13:23 +03:00
committed by GitHub
parent e720844ff6
commit b7d5452c1d
+49 -17
View File
@@ -23,6 +23,7 @@
#include "KAssert.h"
#include "Atomic.h"
#include "Exceptions.h"
#include "KString.h"
#include "Memory.h"
#include "MemoryPrivate.hpp"
#include "Natives.h"
@@ -226,7 +227,7 @@ public:
keys[index++] = it.first;
}
std::sort(keys.begin(), keys.end());
for (auto& it : keys) {
for (auto* it : keys) {
konan::consolePrintf(
"%d bytes -> %d times\n", it, (*allocationHistogram)[it]);
}
@@ -611,7 +612,7 @@ inline void DecrementRC(ContainerHeader* container) {
} else if (UseCycleCollector) { // Possible root.
RuntimeAssert(!Atomic, "Cycle collector shalln't be used with shared objects yet");
RuntimeAssert(container->objectCount() == 1,
"Cycle collector shall only work with single object containers");
"cycle collector shall only work with single object containers");
// We do not use cycle collector for frozen objects, as we already detected
// possible cycles during freezing.
// Also do not use cycle collector for provable acyclic objects.
@@ -639,11 +640,47 @@ inline void initThreshold(MemoryState* state, uint32_t gcThreshold) {
}
#endif // USE_GC
#if TRACE_MEMORY || USE_GC
#if TRACE_MEMORY && USE_GC
const char* colorNames[] = {"BLACK", "GRAY", "WHITE", "PURPLE", "GREEN", "ORANGE", "RED"};
void dumpObject(ObjHeader* ref, int indent) {
for (int i = 0; i < indent; i++) MEMORY_LOG(" ");
auto* typeInfo = ref->type_info();
auto* packageName =
typeInfo->packageName_ != nullptr ? CreateCStringFromString(typeInfo->packageName_) : nullptr;
auto* relativeName =
typeInfo->relativeName_ != nullptr ? CreateCStringFromString(typeInfo->relativeName_) : nullptr;
MEMORY_LOG("%p %s.%s\n", ref,
packageName ? packageName : "<unknown>", relativeName ? relativeName : "<unknown>");
if (packageName) konan::free(packageName);
if (relativeName) konan::free(relativeName);
}
void dumpContainerContent(ContainerHeader* container) {
if (isAggregatingFrozenContainer(container)) {
MEMORY_LOG("%s aggregating container %p with %d objects rc=%d\n",
colorNames[container->color()], container, container->objectCount(), container->refCount());
ContainerHeader** subContainer = reinterpret_cast<ContainerHeader**>(container + 1);
for (int i = 0; i < container->objectCount(); ++i) {
ObjHeader* obj = reinterpret_cast<ObjHeader*>(subContainer + 1);
MEMORY_LOG(" object %p of type %p: ", obj, obj->type_info());
dumpObject(obj, 4);
}
} else {
MEMORY_LOG("%s regular %s%scontainer %p with %d objects rc=%d\n",
colorNames[container->color()],
container->frozen() ? "frozen " : "",
container->stack() ? "stack " : "",
container, container->objectCount(),
container->refCount());
ObjHeader* obj = reinterpret_cast<ObjHeader*>(container + 1);
dumpObject(obj, 4);
}
}
void dumpWorker(const char* prefix, ContainerHeader* header, ContainerHeaderSet* seen) {
MEMORY_LOG("%s: %p (%08x): %d refs\n", prefix, header, header->refCount_,
header->refCount_ >> CONTAINER_TAG_SHIFT)
dumpContainerContent(header);
seen->insert(header);
traverseContainerReferredObjects(header, [prefix, seen](ObjHeader* ref) {
auto* child = ref->container();
@@ -656,10 +693,7 @@ void dumpWorker(const char* prefix, ContainerHeader* header, ContainerHeaderSet*
void dumpReachable(const char* prefix, const ContainerHeaderSet* roots) {
ContainerHeaderSet seen;
for (auto container : *roots) {
MEMORY_LOG("%p: %s%s\n", container,
container->frozen() ? "frozen " : "",
container->stack() ? "stack " : "")
for (auto* container : *roots) {
dumpWorker(prefix, container, &seen);
}
}
@@ -673,10 +707,6 @@ void ScanRoots(MemoryState*);
void CollectRoots(MemoryState*);
void Scan(ContainerHeader* container);
#if TRACE_MEMORY
const char* colorNames[] = {"BLACK", "GRAY", "WHITE", "PURPLE", "GREEN", "ORANGE", "RED"};
#endif
template<bool useColor>
void MarkGray(ContainerHeader* start) {
ContainerHeaderDeque toVisit;
@@ -699,8 +729,9 @@ void MarkGray(ContainerHeader* start) {
if (container->marked()) continue;
container->mark();
}
traverseContainerReferredObjects(container, [&toVisit](ObjHeader* ref) {
auto childContainer = ref->container();
auto* childContainer = ref->container();
RuntimeAssert(!isArena(childContainer), "A reference to local object is encountered");
if (!Shareable(childContainer)) {
childContainer->decRefCount<false>();
@@ -714,15 +745,16 @@ template<bool useColor>
void ScanBlack(ContainerHeader* start) {
ContainerHeaderDeque toVisit;
toVisit.push_front(start);
while (!toVisit.empty()) {
auto* container = toVisit.front();
MEMORY_LOG("ScanBlack visit %p [%s]\n", container, colorNames[container->color()]);
toVisit.pop_front();
if (useColor) {
if (container->color() == CONTAINER_TAG_GC_GREEN) continue;
auto color = container->color();
if (color == CONTAINER_TAG_GC_GREEN || color == CONTAINER_TAG_GC_BLACK) continue;
container->setColorAssertIfGreen(CONTAINER_TAG_GC_BLACK);
} else {
if (container->marked()) continue;
container->unMark();
}
traverseContainerReferredObjects(container, [&toVisit](ObjHeader* ref) {
@@ -775,7 +807,7 @@ void MarkRoots(MemoryState* state) {
}
void ScanRoots(MemoryState* state) {
for (auto container : *(state->roots)) {
for (auto* container : *(state->roots)) {
Scan(container);
}
}