Freeze top-level val. (#1906)
This commit is contained in:
+1
-2
@@ -173,7 +173,6 @@ object KotlinTypes {
|
|||||||
val set by CollectionClassifier
|
val set by CollectionClassifier
|
||||||
val map by CollectionClassifier
|
val map by CollectionClassifier
|
||||||
|
|
||||||
|
|
||||||
val nativePtr by InteropType
|
val nativePtr by InteropType
|
||||||
|
|
||||||
val cOpaque by InteropType
|
val cOpaque by InteropType
|
||||||
@@ -198,7 +197,6 @@ object KotlinTypes {
|
|||||||
val cFunction by InteropClassifier
|
val cFunction by InteropClassifier
|
||||||
|
|
||||||
val objCObjectVar by InteropClassifier
|
val objCObjectVar by InteropClassifier
|
||||||
val objCStringVarOf by InteropClassifier
|
|
||||||
|
|
||||||
val objCObjectBase by InteropClassifier
|
val objCObjectBase by InteropClassifier
|
||||||
val objCObjectBaseMeta by InteropClassifier
|
val objCObjectBaseMeta by InteropClassifier
|
||||||
@@ -220,6 +218,7 @@ object KotlinTypes {
|
|||||||
|
|
||||||
private object InteropClassifier : ClassifierAtPackage("kotlinx.cinterop")
|
private object InteropClassifier : ClassifierAtPackage("kotlinx.cinterop")
|
||||||
private object InteropType : TypeAtPackage("kotlinx.cinterop")
|
private object InteropType : TypeAtPackage("kotlinx.cinterop")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class KotlinFile(
|
abstract class KotlinFile(
|
||||||
|
|||||||
+4
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
|||||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||||
import org.jetbrains.kotlin.ir.types.typeWith
|
import org.jetbrains.kotlin.ir.types.typeWith
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -367,6 +368,9 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
|
|||||||
|
|
||||||
val listOfInternal = internalFunction("listOfInternal")
|
val listOfInternal = internalFunction("listOfInternal")
|
||||||
|
|
||||||
|
val threadLocal =
|
||||||
|
context.builtIns.builtInsModule.findClassAcrossModuleDependencies(ClassId.topLevel(FqName("kotlin.native.ThreadLocal")))!!
|
||||||
|
|
||||||
private fun internalFunction(name: String): IrSimpleFunctionSymbol =
|
private fun internalFunction(name: String): IrSimpleFunctionSymbol =
|
||||||
symbolTable.referenceSimpleFunction(context.getInternalFunctions(name).single())
|
symbolTable.referenceSimpleFunction(context.getInternalFunctions(name).single())
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -307,7 +307,7 @@ internal val ClassDescriptor.objectInstanceShadowFieldSymbolName: String
|
|||||||
assert (this.isExported())
|
assert (this.isExported())
|
||||||
assert (this.kind.isSingleton)
|
assert (this.kind.isSingleton)
|
||||||
assert (!this.isUnit())
|
assert (!this.isUnit())
|
||||||
assert (this.symbol.objectIsShared)
|
assert (this.objectIsShared)
|
||||||
|
|
||||||
return "kshadowobjref:$fqNameSafe"
|
return "kshadowobjref:$fqNameSafe"
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-2
@@ -77,7 +77,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
|||||||
|
|
||||||
fun getObjectInstanceShadowStorage(descriptor: ClassDescriptor): LLVMValueRef {
|
fun getObjectInstanceShadowStorage(descriptor: ClassDescriptor): LLVMValueRef {
|
||||||
assert (!descriptor.isUnit())
|
assert (!descriptor.isUnit())
|
||||||
assert (descriptor.symbol.objectIsShared)
|
assert (descriptor.objectIsShared)
|
||||||
val llvmGlobal = if (!isExternal(descriptor)) {
|
val llvmGlobal = if (!isExternal(descriptor)) {
|
||||||
context.llvmDeclarations.forSingleton(descriptor).instanceShadowFieldRef!!
|
context.llvmDeclarations.forSingleton(descriptor).instanceShadowFieldRef!!
|
||||||
} else {
|
} else {
|
||||||
@@ -300,6 +300,11 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun freeze(value: LLVMValueRef, exceptionHandler: ExceptionHandler) {
|
||||||
|
if (isObjectRef(value))
|
||||||
|
call(context.llvm.freezeSubgraph, listOf(value), Lifetime.IRRELEVANT, exceptionHandler)
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateReturnRef(value: LLVMValueRef, address: LLVMValueRef) {
|
private fun updateReturnRef(value: LLVMValueRef, address: LLVMValueRef) {
|
||||||
call(context.llvm.updateReturnRefFunction, listOf(address, value))
|
call(context.llvm.updateReturnRefFunction, listOf(address, value))
|
||||||
}
|
}
|
||||||
@@ -694,7 +699,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val shared = descriptor.symbol.objectIsShared && context.config.threadsAreAllowed
|
val shared = descriptor.objectIsShared && context.config.threadsAreAllowed
|
||||||
val objectPtr = codegen.getObjectInstanceStorage(descriptor, shared)
|
val objectPtr = codegen.getObjectInstanceStorage(descriptor, shared)
|
||||||
val bbCurrent = currentBlock
|
val bbCurrent = currentBlock
|
||||||
val bbInit= basicBlock("label_init", locationInfo)
|
val bbInit= basicBlock("label_init", locationInfo)
|
||||||
|
|||||||
+1
@@ -418,6 +418,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
|||||||
val appendToInitalizersTail = importRtFunction("AppendToInitializersTail")
|
val appendToInitalizersTail = importRtFunction("AppendToInitializersTail")
|
||||||
val initRuntimeIfNeeded = importRtFunction("Kotlin_initRuntimeIfNeeded")
|
val initRuntimeIfNeeded = importRtFunction("Kotlin_initRuntimeIfNeeded")
|
||||||
val mutationCheck = importRtFunction("MutationCheck")
|
val mutationCheck = importRtFunction("MutationCheck")
|
||||||
|
val freezeSubgraph = importRtFunction("FreezeSubgraph")
|
||||||
|
|
||||||
val createKotlinObjCClass by lazy { importRtFunction("CreateKotlinObjCClass") }
|
val createKotlinObjCClass by lazy { importRtFunction("CreateKotlinObjCClass") }
|
||||||
val getObjCKotlinTypeInfo by lazy { importRtFunction("GetObjCKotlinTypeInfo") }
|
val getObjCKotlinTypeInfo by lazy { importRtFunction("GetObjCKotlinTypeInfo") }
|
||||||
|
|||||||
+45
-12
@@ -50,9 +50,12 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
|||||||
|
|
||||||
private val threadLocalAnnotationFqName = FqName("kotlin.native.ThreadLocal")
|
private val threadLocalAnnotationFqName = FqName("kotlin.native.ThreadLocal")
|
||||||
|
|
||||||
val IrClassSymbol.objectIsShared get() =
|
val IrClass.objectIsShared get() =
|
||||||
!descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName)
|
!descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName)
|
||||||
|
|
||||||
|
val IrField.isShared get() =
|
||||||
|
!descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName) && !descriptor.isVar
|
||||||
|
|
||||||
internal fun emitLLVM(context: Context, phaser: PhaseManager) {
|
internal fun emitLLVM(context: Context, phaser: PhaseManager) {
|
||||||
val irModule = context.irModule!!
|
val irModule = context.irModule!!
|
||||||
|
|
||||||
@@ -373,14 +376,16 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
val INIT_GLOBALS = 0
|
val INIT_GLOBALS = 0
|
||||||
val DEINIT_THREAD_LOCAL_GLOBALS = 1
|
val INIT_THREAD_LOCAL_GLOBALS = 1
|
||||||
val DEINIT_GLOBALS = 2
|
val DEINIT_THREAD_LOCAL_GLOBALS = 2
|
||||||
|
val DEINIT_GLOBALS = 3
|
||||||
|
|
||||||
private fun createInitBody(): LLVMValueRef {
|
private fun createInitBody(): LLVMValueRef {
|
||||||
val initFunction = LLVMAddFunction(context.llvmModule, "", kInitFuncType)!!
|
val initFunction = LLVMAddFunction(context.llvmModule, "", kInitFuncType)!!
|
||||||
generateFunction(codegen, initFunction) {
|
generateFunction(codegen, initFunction) {
|
||||||
using(FunctionScope(initFunction, "init_body", it)) {
|
using(FunctionScope(initFunction, "init_body", it)) {
|
||||||
val bbInit = basicBlock("init", null)
|
val bbInit = basicBlock("init", null)
|
||||||
|
val bbLocalInit = basicBlock("local_init", null)
|
||||||
val bbLocalDeinit = basicBlock("local_deinit", null)
|
val bbLocalDeinit = basicBlock("local_deinit", null)
|
||||||
val bbGlobalDeinit = basicBlock("global_deinit", null)
|
val bbGlobalDeinit = basicBlock("global_deinit", null)
|
||||||
val bbDefault = basicBlock("default", null) {
|
val bbDefault = basicBlock("default", null) {
|
||||||
@@ -389,6 +394,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
switch(LLVMGetParam(initFunction, 0)!!,
|
switch(LLVMGetParam(initFunction, 0)!!,
|
||||||
listOf(Int32(INIT_GLOBALS).llvm to bbInit,
|
listOf(Int32(INIT_GLOBALS).llvm to bbInit,
|
||||||
|
Int32(INIT_THREAD_LOCAL_GLOBALS).llvm to bbLocalInit,
|
||||||
Int32(DEINIT_THREAD_LOCAL_GLOBALS).llvm to bbLocalDeinit,
|
Int32(DEINIT_THREAD_LOCAL_GLOBALS).llvm to bbLocalDeinit,
|
||||||
Int32(DEINIT_GLOBALS).llvm to bbGlobalDeinit),
|
Int32(DEINIT_GLOBALS).llvm to bbGlobalDeinit),
|
||||||
bbDefault)
|
bbDefault)
|
||||||
@@ -398,9 +404,26 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
context.llvm.fileInitializers
|
context.llvm.fileInitializers
|
||||||
.forEach {
|
.forEach {
|
||||||
if (it.initializer?.expression !is IrConst<*>?) {
|
if (it.initializer?.expression !is IrConst<*>?) {
|
||||||
val initialization = evaluateExpression(it.initializer!!.expression)
|
if (it.isShared) {
|
||||||
val address = context.llvmDeclarations.forStaticField(it).storage
|
val initialization = evaluateExpression(it.initializer!!.expression)
|
||||||
storeAny(initialization, address)
|
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||||
|
freeze(initialization, currentCodeContext.exceptionHandler)
|
||||||
|
storeAny(initialization, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
appendingTo(bbLocalInit) {
|
||||||
|
context.llvm.fileInitializers
|
||||||
|
.forEach {
|
||||||
|
if (it.initializer?.expression !is IrConst<*>?) {
|
||||||
|
if (!it.isShared) {
|
||||||
|
val initialization = evaluateExpression(it.initializer!!.expression)
|
||||||
|
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||||
|
storeAny(initialization, address)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret(null)
|
ret(null)
|
||||||
@@ -408,17 +431,25 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
appendingTo(bbLocalDeinit) {
|
appendingTo(bbLocalDeinit) {
|
||||||
context.llvm.fileInitializers.forEach {
|
context.llvm.fileInitializers.forEach {
|
||||||
val descriptor = it
|
// Only if a subject for memory management.
|
||||||
if (!descriptor.type.binaryTypeIsReference())
|
if (it.type.binaryTypeIsReference() && !it.isShared) {
|
||||||
return@forEach // Is not a subject for memory management.
|
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||||
val address = context.llvmDeclarations.forStaticField(descriptor).storage
|
storeAny(codegen.kNullObjHeaderPtr, address)
|
||||||
storeAny(codegen.kNullObjHeaderPtr, address)
|
}
|
||||||
}
|
}
|
||||||
context.llvm.objects.forEach { storeAny(codegen.kNullObjHeaderPtr, it) }
|
context.llvm.objects.forEach { storeAny(codegen.kNullObjHeaderPtr, it) }
|
||||||
ret(null)
|
ret(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
appendingTo(bbGlobalDeinit) {
|
appendingTo(bbGlobalDeinit) {
|
||||||
|
context.llvm.fileInitializers
|
||||||
|
// Only if a subject for memory management.
|
||||||
|
.forEach {
|
||||||
|
if (it.type.binaryTypeIsReference() && it.isShared) {
|
||||||
|
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||||
|
storeAny(codegen.kNullObjHeaderPtr, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
context.llvm.sharedObjects.forEach { storeAny(codegen.kNullObjHeaderPtr, it) }
|
context.llvm.sharedObjects.forEach { storeAny(codegen.kNullObjHeaderPtr, it) }
|
||||||
ret(null)
|
ret(null)
|
||||||
}
|
}
|
||||||
@@ -1426,8 +1457,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
}
|
}
|
||||||
functionGenerationContext.storeAny(valueToAssign, fieldPtrOfClass(thisPtr, value.symbol.owner))
|
functionGenerationContext.storeAny(valueToAssign, fieldPtrOfClass(thisPtr, value.symbol.owner))
|
||||||
} else {
|
} else {
|
||||||
assert (value.receiver == null)
|
assert(value.receiver == null)
|
||||||
val globalValue = context.llvmDeclarations.forStaticField(value.symbol.owner).storage
|
val globalValue = context.llvmDeclarations.forStaticField(value.symbol.owner).storage
|
||||||
|
if (value.symbol.owner.isShared)
|
||||||
|
functionGenerationContext.freeze(valueToAssign, currentCodeContext.exceptionHandler)
|
||||||
functionGenerationContext.storeAny(valueToAssign, globalValue)
|
functionGenerationContext.storeAny(valueToAssign, globalValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -330,7 +330,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
} else {
|
} else {
|
||||||
"kobjref:" + qualifyInternalName(descriptor)
|
"kobjref:" + qualifyInternalName(descriptor)
|
||||||
}
|
}
|
||||||
val threadLocal = !(descriptor.symbol.objectIsShared && context.config.threadsAreAllowed)
|
val threadLocal = !(descriptor.objectIsShared && context.config.threadsAreAllowed)
|
||||||
val instanceFieldRef = addGlobal(
|
val instanceFieldRef = addGlobal(
|
||||||
symbolName, getLLVMType(descriptor.defaultType), isExported = isExported, threadLocal = threadLocal)
|
symbolName, getLLVMType(descriptor.defaultType), isExported = isExported, threadLocal = threadLocal)
|
||||||
|
|
||||||
@@ -390,7 +390,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
val name = "kvar:" + qualifyInternalName(descriptor)
|
val name = "kvar:" + qualifyInternalName(descriptor)
|
||||||
|
|
||||||
val storage = addGlobal(
|
val storage = addGlobal(
|
||||||
name, getLLVMType(descriptor.type), isExported = false, threadLocal = true)
|
name, getLLVMType(descriptor.type), isExported = false, threadLocal = !declaration.isShared)
|
||||||
|
|
||||||
this.staticFields[descriptor] = StaticFieldLlvmDeclarations(storage)
|
this.staticFields[descriptor] = StaticFieldLlvmDeclarations(storage)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.llvm
|
package org.jetbrains.kotlin.backend.konan.llvm
|
||||||
|
|
||||||
import llvm.*
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
@@ -121,7 +122,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
|
|
||||||
internal fun createImmutable(descriptor: ValueDescriptor, value: LLVMValueRef) : Int {
|
internal fun createImmutable(descriptor: ValueDescriptor, value: LLVMValueRef) : Int {
|
||||||
if (contextVariablesToIndex.containsKey(descriptor))
|
if (contextVariablesToIndex.containsKey(descriptor))
|
||||||
throw Error("$descriptor is already defined")
|
throw Error("${ir2string(descriptor)} is already defined")
|
||||||
val index = variables.size
|
val index = variables.size
|
||||||
variables.add(ValueRecord(value, descriptor.name))
|
variables.add(ValueRecord(value, descriptor.name))
|
||||||
contextVariablesToIndex[descriptor] = index
|
contextVariablesToIndex[descriptor] = index
|
||||||
|
|||||||
+1
-1
@@ -69,7 +69,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
currentFile = irFile
|
currentFile = irFile
|
||||||
irFile.transformChildrenVoid(this)
|
irFile.transformChildrenVoid(this)
|
||||||
|
|
||||||
topLevelInitializers.forEach { irFile.addTopLevelInitializer(it) }
|
topLevelInitializers.forEach { irFile.addTopLevelInitializer(it, context, false) }
|
||||||
topLevelInitializers.clear()
|
topLevelInitializers.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -565,8 +565,8 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
irFile.addChild(ir)
|
irFile.addChild(ir)
|
||||||
val irConstructor = ir.constructors.single()
|
val irConstructor = ir.constructors.single()
|
||||||
irFile.addTopLevelInitializer(
|
irFile.addTopLevelInitializer(
|
||||||
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irConstructor.returnType, irConstructor.symbol)
|
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irConstructor.returnType, irConstructor.symbol),
|
||||||
)
|
context, threadLocal = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check if this fqName already used or not. */
|
/** Check if this fqName already used or not. */
|
||||||
@@ -587,6 +587,8 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: an awful hack, we make this initializer thread local, so that it doesn't freeze suite,
|
||||||
|
// and later on we could modify some suite's properties. This shall be redesigned.
|
||||||
irFile.addTopLevelInitializer(builder.irBlock {
|
irFile.addTopLevelInitializer(builder.irBlock {
|
||||||
val constructorCall = irCall(symbols.topLevelSuiteConstructor).apply {
|
val constructorCall = irCall(symbols.topLevelSuiteConstructor).apply {
|
||||||
putValueArgument(0, IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
putValueArgument(0, IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
@@ -597,7 +599,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
symbols.topLevelSuiteRegisterTestCase,
|
symbols.topLevelSuiteRegisterTestCase,
|
||||||
symbols.topLevelSuiteRegisterFunction,
|
symbols.topLevelSuiteRegisterFunction,
|
||||||
functions)
|
functions)
|
||||||
})
|
}, context, threadLocal = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTestSuites(irFile: IrFile, annotationCollector: AnnotationCollector) {
|
private fun createTestSuites(irFile: IrFile, annotationCollector: AnnotationCollector) {
|
||||||
|
|||||||
+12
-7
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.ir.util
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.substitute
|
import org.jetbrains.kotlin.backend.common.descriptors.substitute
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanCompilationException
|
import org.jetbrains.kotlin.backend.konan.KonanCompilationException
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
@@ -27,7 +28,9 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
|
||||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
@@ -47,7 +50,6 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.OverridingStrategy
|
import org.jetbrains.kotlin.resolve.OverridingStrategy
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||||
@@ -58,10 +60,14 @@ internal fun IrExpression.isNullConst() = this is IrConst<*> && this.kind == IrC
|
|||||||
|
|
||||||
private var topLevelInitializersCounter = 0
|
private var topLevelInitializersCounter = 0
|
||||||
|
|
||||||
internal fun IrFile.addTopLevelInitializer(expression: IrExpression) {
|
internal fun IrFile.addTopLevelInitializer(expression: IrExpression, context: KonanBackendContext, threadLocal: Boolean) {
|
||||||
val fieldDescriptor = PropertyDescriptorImpl.create(
|
val fieldDescriptor = PropertyDescriptorImpl.create(
|
||||||
this.packageFragmentDescriptor,
|
this.packageFragmentDescriptor,
|
||||||
Annotations.EMPTY,
|
if (threadLocal)
|
||||||
|
AnnotationsImpl(listOf(AnnotationDescriptorImpl(context.ir.symbols.threadLocal.defaultType,
|
||||||
|
emptyMap(), SourceElement.NO_SOURCE)))
|
||||||
|
else
|
||||||
|
Annotations.EMPTY,
|
||||||
Modality.FINAL,
|
Modality.FINAL,
|
||||||
Visibilities.PRIVATE,
|
Visibilities.PRIVATE,
|
||||||
false,
|
false,
|
||||||
@@ -76,7 +82,6 @@ internal fun IrFile.addTopLevelInitializer(expression: IrExpression) {
|
|||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
|
||||||
val builtIns = fieldDescriptor.builtIns
|
|
||||||
fieldDescriptor.setType(expression.type.toKotlinType(), emptyList(), null, null as KotlinType?)
|
fieldDescriptor.setType(expression.type.toKotlinType(), emptyList(), null, null as KotlinType?)
|
||||||
fieldDescriptor.initialize(null, null)
|
fieldDescriptor.initialize(null, null)
|
||||||
|
|
||||||
@@ -123,8 +128,8 @@ private fun createFakeOverride(
|
|||||||
is PropertyDescriptor ->
|
is PropertyDescriptor ->
|
||||||
IrPropertyImpl(startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, descriptor).apply {
|
IrPropertyImpl(startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, descriptor).apply {
|
||||||
// TODO: add field if getter is missing?
|
// TODO: add field if getter is missing?
|
||||||
getter = descriptor.getter?.createFunction() as IrSimpleFunction?
|
getter = descriptor.getter?.createFunction()
|
||||||
setter = descriptor.setter?.createFunction() as IrSimpleFunction?
|
setter = descriptor.setter?.createFunction()
|
||||||
}
|
}
|
||||||
else -> TODO(descriptor.toString())
|
else -> TODO(descriptor.toString())
|
||||||
}
|
}
|
||||||
@@ -238,7 +243,7 @@ fun IrSimpleFunction.setOverrides(symbolTable: ReferenceSymbolTable) {
|
|||||||
fun IrClass.simpleFunctions(): List<IrSimpleFunction> = this.declarations.flatMap {
|
fun IrClass.simpleFunctions(): List<IrSimpleFunction> = this.declarations.flatMap {
|
||||||
when (it) {
|
when (it) {
|
||||||
is IrSimpleFunction -> listOf(it)
|
is IrSimpleFunction -> listOf(it)
|
||||||
is IrProperty -> listOfNotNull(it.getter as IrSimpleFunction?, it.setter as IrSimpleFunction?)
|
is IrProperty -> listOfNotNull(it.getter, it.setter)
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ fun bar(b: B) {
|
|||||||
foo(c)
|
foo(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ThreadLocal
|
||||||
val global = B()
|
val global = B()
|
||||||
|
|
||||||
@Test fun runTest() {
|
@Test fun runTest() {
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ class Graph(val nodes: List<Node>, val roots: List<Node>)
|
|||||||
fun min(x: Int, y: Int) = if (x < y) x else y
|
fun min(x: Int, y: Int) = if (x < y) x else y
|
||||||
fun max(x: Int, y: Int) = if (x > y) x else y
|
fun max(x: Int, y: Int) = if (x > y) x else y
|
||||||
|
|
||||||
|
@ThreadLocal
|
||||||
val random = Random(42)
|
val random = Random(42)
|
||||||
|
|
||||||
fun generate(condensationSize: Int, branchingFactor: Int, swellingFactor: Int): Graph {
|
fun generate(condensationSize: Int, branchingFactor: Int, swellingFactor: Int): Graph {
|
||||||
|
|||||||
@@ -1667,7 +1667,7 @@ void freezeCyclic(ContainerHeader* rootContainer, const KStdVector<ContainerHead
|
|||||||
* Theory of operations.
|
* Theory of operations.
|
||||||
*
|
*
|
||||||
* Kotlin/Native supports object graph freezing, allowing to make certain subgraph immutable and thus
|
* Kotlin/Native supports object graph freezing, allowing to make certain subgraph immutable and thus
|
||||||
* suitable for safe sharing amongs multiple concurrent executors. This operation recursively operates
|
* suitable for safe sharing amongst multiple concurrent executors. This operation recursively operates
|
||||||
* on all objects reachable from the given object, and marks them as frozen. In frozen state object's
|
* on all objects reachable from the given object, and marks them as frozen. In frozen state object's
|
||||||
* fields cannot be modified, and so, lifetime of frozen objects correlates. Practically, it means
|
* fields cannot be modified, and so, lifetime of frozen objects correlates. Practically, it means
|
||||||
* that lifetimes of all strongly connected components are fully controlled by incoming reference
|
* that lifetimes of all strongly connected components are fully controlled by incoming reference
|
||||||
@@ -1687,6 +1687,7 @@ void freezeCyclic(ContainerHeader* rootContainer, const KStdVector<ContainerHead
|
|||||||
* references could be passed across multiple threads.
|
* references could be passed across multiple threads.
|
||||||
*/
|
*/
|
||||||
void FreezeSubgraph(ObjHeader* root) {
|
void FreezeSubgraph(ObjHeader* root) {
|
||||||
|
if (root == nullptr) return;
|
||||||
// First check that passed object graph has no cycles.
|
// First check that passed object graph has no cycles.
|
||||||
// If there are cycles - run graph condensation on cyclic graphs using Kosoraju-Sharir.
|
// If there are cycles - run graph condensation on cyclic graphs using Kosoraju-Sharir.
|
||||||
ContainerHeader* rootContainer = root->container();
|
ContainerHeader* rootContainer = root->container();
|
||||||
|
|||||||
@@ -39,8 +39,9 @@ InitNode* initTailNode = nullptr;
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
INIT_GLOBALS = 0,
|
INIT_GLOBALS = 0,
|
||||||
DEINIT_THREAD_LOCAL_GLOBALS = 1,
|
INIT_THREAD_LOCAL_GLOBALS = 1,
|
||||||
DEINIT_GLOBALS = 2
|
DEINIT_THREAD_LOCAL_GLOBALS = 2,
|
||||||
|
DEINIT_GLOBALS = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -78,10 +79,13 @@ RuntimeState* initRuntime() {
|
|||||||
RuntimeState* result = konanConstructInstance<RuntimeState>();
|
RuntimeState* result = konanConstructInstance<RuntimeState>();
|
||||||
if (!result) return nullptr;
|
if (!result) return nullptr;
|
||||||
result->memoryState = InitMemory();
|
result->memoryState = InitMemory();
|
||||||
|
bool firstRuntime = atomicAdd(&aliveRuntimesCount, 1) == 1;
|
||||||
// Keep global variables in state as well.
|
// Keep global variables in state as well.
|
||||||
InitOrDeinitGlobalVariables(INIT_GLOBALS);
|
if (firstRuntime) {
|
||||||
konan::consoleInit();
|
konan::consoleInit();
|
||||||
atomicAdd(&aliveRuntimesCount, 1);
|
InitOrDeinitGlobalVariables(INIT_GLOBALS);
|
||||||
|
}
|
||||||
|
InitOrDeinitGlobalVariables(INIT_THREAD_LOCAL_GLOBALS);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package kotlin.native.test
|
|||||||
|
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
@ThreadLocal
|
||||||
private val _generatedSuites = mutableListOf<TestSuite>()
|
private val _generatedSuites = mutableListOf<TestSuite>()
|
||||||
|
|
||||||
internal fun registerSuite(suite: TestSuite): Unit {
|
internal fun registerSuite(suite: TestSuite): Unit {
|
||||||
|
|||||||
@@ -173,9 +173,19 @@ class AtomicReference<T>(private var value: T? = null) {
|
|||||||
external public fun get(): T?
|
external public fun get(): T?
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object UNINITIALIZED
|
internal object UNINITIALIZED {
|
||||||
|
// So that single-threaded configs can use those as well.
|
||||||
|
init {
|
||||||
|
freeze()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal object INITIALIZING
|
internal object INITIALIZING {
|
||||||
|
// So that single-threaded configs can use those as well.
|
||||||
|
init {
|
||||||
|
freeze()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Frozen
|
@Frozen
|
||||||
internal class AtomicLazyImpl<out T>(initializer: () -> T) : Lazy<T> {
|
internal class AtomicLazyImpl<out T>(initializer: () -> T) : Lazy<T> {
|
||||||
|
|||||||
Reference in New Issue
Block a user