Fix object sharing and early instance allocations. (#2908)

This commit is contained in:
Nikolay Igotti
2019-04-23 16:43:39 +03:00
committed by GitHub
parent a6f1048e8a
commit a764723e4f
+18 -12
View File
@@ -510,8 +510,8 @@ inline container_size_t alignUp(container_size_t size, int alignment) {
return (size + alignment - 1) & ~(alignment - 1); return (size + alignment - 1) & ~(alignment - 1);
} }
inline ContainerHeader* realFrozenContainer(ContainerHeader* container) { inline ContainerHeader* realShareableContainer(ContainerHeader* container) {
RuntimeAssert(container->frozen(), "Only makes sense on frozen objects"); RuntimeAssert(container->shareable(), "Only makes sense on shareable objects");
return reinterpret_cast<ObjHeader*>(container + 1)->container(); return reinterpret_cast<ObjHeader*>(container + 1)->container();
} }
@@ -1190,7 +1190,8 @@ ContainerHeader* AllocContainer(MemoryState* state, size_t size) {
ContainerHeader* result = nullptr; ContainerHeader* result = nullptr;
#if USE_GC #if USE_GC
// We recycle elements of finalizer queue for new allocations, to avoid trashing memory manager. // We recycle elements of finalizer queue for new allocations, to avoid trashing memory manager.
ContainerHeader *container = state->finalizerQueue, *previous = nullptr; ContainerHeader* container = state != nullptr ? state->finalizerQueue : nullptr;
ContainerHeader* previous = nullptr;
while (container != nullptr) { while (container != nullptr) {
// TODO: shall it be == instead? // TODO: shall it be == instead?
if (container->hasContainerSize() && if (container->hasContainerSize() &&
@@ -1213,10 +1214,12 @@ ContainerHeader* AllocContainer(MemoryState* state, size_t size) {
result = konanConstructSizedInstance<ContainerHeader>(alignUp(size, kObjectAlignment)); result = konanConstructSizedInstance<ContainerHeader>(alignUp(size, kObjectAlignment));
atomicAdd(&allocCount, 1); atomicAdd(&allocCount, 1);
} }
CONTAINER_ALLOC_EVENT(state, size, result); if (state != nullptr) {
CONTAINER_ALLOC_EVENT(state, size, result);
#if TRACE_MEMORY #if TRACE_MEMORY
state->containers->insert(result); state->containers->insert(result);
#endif #endif
}
return result; return result;
} }
@@ -1429,10 +1432,10 @@ void incrementStack(MemoryState* state) {
} }
} }
void actualizeNewlyFrozenOnStack(MemoryState* state, const ContainerHeaderSet* newlyFrozen) { void actualizeNewlySharedOnStack(MemoryState* state, const ContainerHeaderSet* newlyShared) {
// For all frozen objects in stack slots - perform reference increment. // For all frozen objects in stack slots - perform reference increment.
FrameOverlay* frame = currentFrame; FrameOverlay* frame = currentFrame;
MEMORY_LOG("actualizeNewlyFrozenOnStack: newly frozen size is %d\n", newlyFrozen->size()) MEMORY_LOG("actualizeNewlySharedOnStack: newly shared size is %d\n", newlyShared->size())
while (frame != nullptr) { while (frame != nullptr) {
MEMORY_LOG("current frame %p: %d parameters %d locals\n", frame, frame->parameters, frame->count) MEMORY_LOG("current frame %p: %d parameters %d locals\n", frame, frame->parameters, frame->count)
ObjHeader** current = reinterpret_cast<ObjHeader**>(frame + 1) + frame->parameters; ObjHeader** current = reinterpret_cast<ObjHeader**>(frame + 1) + frame->parameters;
@@ -1443,7 +1446,7 @@ void actualizeNewlyFrozenOnStack(MemoryState* state, const ContainerHeaderSet* n
if (obj != nullptr) { if (obj != nullptr) {
auto* container = obj->container(); auto* container = obj->container();
// No need to use atomic increment yet, object is still local. // No need to use atomic increment yet, object is still local.
if (container != nullptr && container->frozen() && newlyFrozen->count(container) != 0) { if (container != nullptr && container->shareable() && newlyShared->count(container) != 0) {
container->incRefCount<false>(); container->incRefCount<false>();
MEMORY_LOG("incremented rc of %p to %d\n", container, container->refCount()); MEMORY_LOG("incremented rc of %p to %d\n", container, container->refCount());
} }
@@ -1454,10 +1457,10 @@ void actualizeNewlyFrozenOnStack(MemoryState* state, const ContainerHeaderSet* n
// And actualize RC of those objects using toRelease set. // And actualize RC of those objects using toRelease set.
for (auto& container : *(state->toRelease)) { for (auto& container : *(state->toRelease)) {
if (!isMarkedAsRemoved(container) && container->frozen()) { if (!isMarkedAsRemoved(container) && container->shareable()) {
RuntimeAssert(newlyFrozen->count(container) != 0, "Must be newly frozen"); RuntimeAssert(newlyShared->count(container) != 0, "Must be newly shared");
// To account for aggregating containers. // To account for aggregating containers.
ContainerHeader* realContainer = realFrozenContainer(container); ContainerHeader* realContainer = realShareableContainer(container);
auto newRc = realContainer->decRefCount<false>(); auto newRc = realContainer->decRefCount<false>();
MEMORY_LOG("decremented rc of %p to %d\n", realContainer, newRc); MEMORY_LOG("decremented rc of %p to %d\n", realContainer, newRc);
container = markAsRemoved(container); container = markAsRemoved(container);
@@ -2311,7 +2314,7 @@ void FreezeSubgraph(ObjHeader* root) {
} }
} }
// Actualize reference counters of newly frozen objects. // Actualize reference counters of newly frozen objects.
actualizeNewlyFrozenOnStack(memoryState, &newlyFrozen); actualizeNewlySharedOnStack(state, &newlyFrozen);
#endif #endif
} }
@@ -2421,6 +2424,9 @@ void Kotlin_Any_share(ObjHeader* obj) {
if (Shareable(container)) return; if (Shareable(container)) return;
RuntimeCheck(container->objectCount() == 1, "Must be a single object container"); RuntimeCheck(container->objectCount() == 1, "Must be a single object container");
container->makeShareable(); container->makeShareable();
ContainerHeaderSet newlyShared;
newlyShared.insert(container);
actualizeNewlySharedOnStack(memoryState, &newlyShared);
} }
} // extern "C" } // extern "C"