From c76c39fafdc37cc31d5785a3639133eaae319644 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Wed, 28 Mar 2018 17:19:29 +0300 Subject: [PATCH] Fixed shared globals deinit --- .../backend/konan/llvm/CodeGenerator.kt | 46 ++++++++----------- .../kotlin/backend/konan/llvm/ContextUtils.kt | 1 + .../kotlin/backend/konan/llvm/IrToBitcode.kt | 27 +++++++++-- runtime/src/main/cpp/Atomic.h | 15 ++++++ runtime/src/main/cpp/Memory.cpp | 9 +--- runtime/src/main/cpp/Runtime.cpp | 23 +++++++--- 6 files changed, 77 insertions(+), 44 deletions(-) create mode 100644 runtime/src/main/cpp/Atomic.h diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index b784a1c8890..ae6c29f43f8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -46,7 +46,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { fun functionEntryPointAddress(descriptor: FunctionDescriptor) = descriptor.entryPointAddress.llvm fun functionHash(descriptor: FunctionDescriptor): LLVMValueRef = descriptor.functionName.localHash.llvm - fun getObjectInstanceStorage(descriptor: ClassDescriptor): LLVMValueRef { + fun getObjectInstanceStorage(descriptor: ClassDescriptor, shared: Boolean): LLVMValueRef { assert (!descriptor.isUnit()) val llvmGlobal = if (!isExternal(descriptor)) { context.llvmDeclarations.forSingleton(descriptor).instanceFieldRef @@ -56,10 +56,13 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { descriptor.objectInstanceFieldSymbolName, llvmType, origin = descriptor.llvmSymbolOrigin, - threadLocal = !descriptor.symbol.objectIsShared + threadLocal = !shared ) } - context.llvm.objects += llvmGlobal + if (shared) + context.llvm.sharedObjects += llvmGlobal + else + context.llvm.objects += llvmGlobal return llvmGlobal } @@ -593,40 +596,31 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, return codegen.theUnitInstanceRef.llvm } - val args = mutableListOf() - val objectPtr = codegen.getObjectInstanceStorage(descriptor) - args += objectPtr + val objectPtr = codegen.getObjectInstanceStorage(descriptor, shared) val bbCurrent = currentBlock - val bbFirstCheck = basicBlock(if (shared) "label_check_shadow" else "label_init", locationInfo) + val bbInit = basicBlock("label_init", locationInfo) val bbExit = basicBlock("label_continue", locationInfo) val objectVal = loadSlot(objectPtr, false) val objectInitialized = icmpUGt(ptrToInt(objectVal, codegen.intPtrType), codegen.immOneIntPtrType) - condBr(objectInitialized, bbExit, bbFirstCheck) - - positionAtEnd(bbExit) - val valuePhi = phi(codegen.getLLVMType(descriptor.defaultType)) - - positionAtEnd(bbFirstCheck) - if (shared) { - val shadowObjectPtr = codegen.getObjectInstanceShadowStorage(descriptor) - args += shadowObjectPtr - val shadowObjectVal = loadSlot(shadowObjectPtr, false) - val shadowNotNull = icmpNe(bitcast(int8TypePtr, shadowObjectVal), kNullInt8Ptr) - val bbInit = basicBlock("label_init", locationInfo) - condBr(shadowNotNull, bbExit, bbInit) - addPhiIncoming(valuePhi, bbFirstCheck to shadowObjectVal) - positionAtEnd(bbInit) - } + condBr(objectInitialized, bbExit, bbInit) + positionAtEnd(bbInit) + val typeInfo = codegen.typeInfoForAllocation(descriptor) val defaultConstructor = descriptor.constructors.first { it.valueParameters.size == 0 } - args += codegen.typeInfoForAllocation(descriptor) - args += codegen.llvmFunction(defaultConstructor) - val initFunction = if (shared) context.llvm.initSharedInstanceFunction else context.llvm.initInstanceFunction + val ctor = codegen.llvmFunction(defaultConstructor) + val (initFunction, args) = + if (shared) { + val shadowObjectPtr = codegen.getObjectInstanceShadowStorage(descriptor) + context.llvm.initSharedInstanceFunction to listOf(objectPtr, shadowObjectPtr, typeInfo, ctor) + } else { + context.llvm.initInstanceFunction to listOf(objectPtr, typeInfo, ctor) + } val newValue = call(initFunction, args, Lifetime.GLOBAL, exceptionHandler) val bbInitResult = currentBlock br(bbExit) positionAtEnd(bbExit) + val valuePhi = phi(codegen.getLLVMType(descriptor.defaultType)) addPhiIncoming(valuePhi, bbCurrent to objectVal, bbInitResult to newValue) return valuePhi diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index f73729cf3e5..0fe411c4391 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -477,6 +477,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { val staticInitializers = mutableListOf() val fileInitializers = mutableListOf() val objects = mutableSetOf() + val sharedObjects = mutableSetOf() private object lazyRtFunction { operator fun provideDelegate( diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 9bcadae8a62..196479de267 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -358,15 +358,28 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map(); if (!result) return nullptr; result->memoryState = InitMemory(); // Keep global variables in state as well. - InitOrDeinitGlobalVariables(true); + InitOrDeinitGlobalVariables(INIT_GLOBALS); konan::consoleInit(); + atomicAdd(&aliveRuntimesCount, 1); return result; } void deinitRuntime(RuntimeState* state) { - if (state != nullptr) { - InitOrDeinitGlobalVariables(false); - DeinitMemory(state->memoryState); - konanDestructInstance(state); - } + bool lastRuntime = atomicAdd(&aliveRuntimesCount, -1) == 0; + InitOrDeinitGlobalVariables(DEINIT_THREAD_LOCAL_GLOBALS); + if (lastRuntime) + InitOrDeinitGlobalVariables(DEINIT_GLOBALS); + DeinitMemory(state->memoryState); + konanDestructInstance(state); } } // namespace