Supported shared access to enums
This commit is contained in:
+1
-1
@@ -70,7 +70,7 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) {
|
|||||||
val constructorDescriptor = implObjectDescriptor.createSimpleDelegatingConstructorDescriptor(constructorOfAny, true)
|
val constructorDescriptor = implObjectDescriptor.createSimpleDelegatingConstructorDescriptor(constructorOfAny, true)
|
||||||
|
|
||||||
implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor)
|
implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor)
|
||||||
val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor).apply {
|
val implObject = IrClassImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, implObjectDescriptor).apply {
|
||||||
createParameterDeclarations()
|
createParameterDeclarations()
|
||||||
addFakeOverrides()
|
addFakeOverrides()
|
||||||
setSuperSymbols(listOf(context.ir.symbols.any.owner))
|
setSuperSymbols(listOf(context.ir.symbols.any.owner))
|
||||||
|
|||||||
+1
@@ -62,6 +62,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
|||||||
|
|
||||||
internal val clang = platform.clang
|
internal val clang = platform.clang
|
||||||
val indirectBranchesAreAllowed = target != KonanTarget.WASM32
|
val indirectBranchesAreAllowed = target != KonanTarget.WASM32
|
||||||
|
val threadsAreAllowed = (target != KonanTarget.WASM32) && (target !is KonanTarget.ZEPHYR)
|
||||||
|
|
||||||
internal val produce get() = configuration.get(KonanConfigKeys.PRODUCE)!!
|
internal val produce get() = configuration.get(KonanConfigKeys.PRODUCE)!!
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -252,7 +252,7 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
|
|||||||
context.getInternalFunctions("initInstance").single())
|
context.getInternalFunctions("initInstance").single())
|
||||||
|
|
||||||
val freeze = symbolTable.referenceSimpleFunction(
|
val freeze = symbolTable.referenceSimpleFunction(
|
||||||
builtInsPackage("konan", "worker").getContributedFunctions(Name.identifier("freeze"), NoLookupLocation.FROM_BACKEND).single())
|
builtInsPackage("konan", "worker").getContributedFunctions(Name.identifier("freezeAllowCycles"), NoLookupLocation.FROM_BACKEND).single())
|
||||||
|
|
||||||
val getContinuation = symbolTable.referenceSimpleFunction(
|
val getContinuation = symbolTable.referenceSimpleFunction(
|
||||||
context.getInternalFunctions("getContinuation").single())
|
context.getInternalFunctions("getContinuation").single())
|
||||||
|
|||||||
+8
-5
@@ -56,7 +56,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
|||||||
descriptor.objectInstanceFieldSymbolName,
|
descriptor.objectInstanceFieldSymbolName,
|
||||||
llvmType,
|
llvmType,
|
||||||
origin = descriptor.llvmSymbolOrigin,
|
origin = descriptor.llvmSymbolOrigin,
|
||||||
threadLocal = true
|
threadLocal = !descriptor.symbol.objectIsShared
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
context.llvm.objects += llvmGlobal
|
context.llvm.objects += llvmGlobal
|
||||||
@@ -450,6 +450,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
fun icmpLt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSLT, arg0, arg1, name)!!
|
fun icmpLt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSLT, arg0, arg1, name)!!
|
||||||
fun icmpLe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSLE, arg0, arg1, name)!!
|
fun icmpLe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSLE, arg0, arg1, name)!!
|
||||||
fun icmpNe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntNE, arg0, arg1, name)!!
|
fun icmpNe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntNE, arg0, arg1, name)!!
|
||||||
|
fun icmpUGt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntUGT, arg0, arg1, name)!!
|
||||||
|
|
||||||
/* floating-point comparisons */
|
/* floating-point comparisons */
|
||||||
fun fcmpEq(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFCmp(builder, LLVMRealPredicate.LLVMRealOEQ, arg0, arg1, name)!!
|
fun fcmpEq(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFCmp(builder, LLVMRealPredicate.LLVMRealOEQ, arg0, arg1, name)!!
|
||||||
@@ -566,6 +567,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
|
|
||||||
fun getObjectValue(
|
fun getObjectValue(
|
||||||
descriptor: ClassDescriptor,
|
descriptor: ClassDescriptor,
|
||||||
|
shared: Boolean,
|
||||||
exceptionHandler: ExceptionHandler,
|
exceptionHandler: ExceptionHandler,
|
||||||
locationInfo: LocationInfo?
|
locationInfo: LocationInfo?
|
||||||
): LLVMValueRef {
|
): LLVMValueRef {
|
||||||
@@ -578,15 +580,16 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
val bbInit = basicBlock("label_init", locationInfo)
|
val bbInit = basicBlock("label_init", locationInfo)
|
||||||
val bbExit = basicBlock("label_continue", locationInfo)
|
val bbExit = basicBlock("label_continue", locationInfo)
|
||||||
val objectVal = loadSlot(objectPtr, false)
|
val objectVal = loadSlot(objectPtr, false)
|
||||||
val condition = icmpNe(objectVal, codegen.kNullObjHeaderPtr)
|
val condition = icmpUGt(ptrToInt(objectVal, codegen.intPtrType), codegen.immOneIntPtrType)
|
||||||
condBr(condition, bbExit, bbInit)
|
condBr(condition, bbExit, bbInit)
|
||||||
|
|
||||||
positionAtEnd(bbInit)
|
positionAtEnd(bbInit)
|
||||||
val typeInfo = codegen.typeInfoForAllocation(descriptor)
|
val typeInfo = codegen.typeInfoForAllocation(descriptor)
|
||||||
val initFunction = descriptor.constructors.first { it.valueParameters.size == 0 }
|
val defaultConstructor = descriptor.constructors.first { it.valueParameters.size == 0 }
|
||||||
val ctor = codegen.llvmFunction(initFunction)
|
val ctor = codegen.llvmFunction(defaultConstructor)
|
||||||
val args = listOf(objectPtr, typeInfo, ctor)
|
val args = listOf(objectPtr, typeInfo, ctor)
|
||||||
val newValue = call(context.llvm.initInstanceFunction, args, Lifetime.GLOBAL, exceptionHandler)
|
val initFunction = if (shared) context.llvm.initSharedInstanceFunction else context.llvm.initInstanceFunction
|
||||||
|
val newValue = call(initFunction, args, Lifetime.GLOBAL, exceptionHandler)
|
||||||
val bbInitResult = currentBlock
|
val bbInitResult = currentBlock
|
||||||
br(bbExit)
|
br(bbExit)
|
||||||
|
|
||||||
|
|||||||
+1
@@ -398,6 +398,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
|||||||
val allocInstanceFunction = importRtFunction("AllocInstance")
|
val allocInstanceFunction = importRtFunction("AllocInstance")
|
||||||
val allocArrayFunction = importRtFunction("AllocArrayInstance")
|
val allocArrayFunction = importRtFunction("AllocArrayInstance")
|
||||||
val initInstanceFunction = importRtFunction("InitInstance")
|
val initInstanceFunction = importRtFunction("InitInstance")
|
||||||
|
val initSharedInstanceFunction = importRtFunction("InitSharedInstance")
|
||||||
val updateReturnRefFunction = importRtFunction("UpdateReturnRef")
|
val updateReturnRefFunction = importRtFunction("UpdateReturnRef")
|
||||||
val updateRefFunction = importRtFunction("UpdateRef")
|
val updateRefFunction = importRtFunction("UpdateRef")
|
||||||
val enterFrameFunction = importRtFunction("EnterFrame")
|
val enterFrameFunction = importRtFunction("EnterFrame")
|
||||||
|
|||||||
+4
-4
@@ -35,10 +35,7 @@ import org.jetbrains.kotlin.ir.SourceManager
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
import org.jetbrains.kotlin.ir.util.getArguments
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
@@ -52,6 +49,8 @@ import org.jetbrains.kotlin.types.typeUtil.isNothing
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
|
||||||
|
val IrClassSymbol.objectIsShared get() = owner.origin == DECLARATION_ORIGIN_ENUM
|
||||||
|
|
||||||
internal fun emitLLVM(context: Context) {
|
internal fun emitLLVM(context: Context) {
|
||||||
val irModule = context.irModule!!
|
val irModule = context.irModule!!
|
||||||
|
|
||||||
@@ -777,6 +776,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
private fun evaluateGetObjectValue(value: IrGetObjectValue): LLVMValueRef =
|
private fun evaluateGetObjectValue(value: IrGetObjectValue): LLVMValueRef =
|
||||||
functionGenerationContext.getObjectValue(
|
functionGenerationContext.getObjectValue(
|
||||||
value.symbol.owner,
|
value.symbol.owner,
|
||||||
|
value.symbol.objectIsShared && context.config.threadsAreAllowed,
|
||||||
currentCodeContext.exceptionHandler,
|
currentCodeContext.exceptionHandler,
|
||||||
value.startLocation
|
value.startLocation
|
||||||
)
|
)
|
||||||
|
|||||||
+2
-1
@@ -313,8 +313,9 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
} else {
|
} else {
|
||||||
"kobjref:" + qualifyInternalName(descriptor)
|
"kobjref:" + qualifyInternalName(descriptor)
|
||||||
}
|
}
|
||||||
|
val threadLocal = !(descriptor.symbol.objectIsShared && context.config.threadsAreAllowed)
|
||||||
val instanceFieldRef = addGlobal(
|
val instanceFieldRef = addGlobal(
|
||||||
symbolName, getLLVMType(descriptor.defaultType), isExported = isExported, threadLocal = true)
|
symbolName, getLLVMType(descriptor.defaultType), isExported = isExported, threadLocal = threadLocal)
|
||||||
|
|
||||||
LLVMSetInitializer(instanceFieldRef, kNullObjHeaderPtr)
|
LLVMSetInitializer(instanceFieldRef, kNullObjHeaderPtr)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -924,7 +924,7 @@ private fun ObjCExportCodeGenerator.createObjectInstanceAdapter(
|
|||||||
return generateObjCToKotlinMethodAdapter(methodBridge, selector) {
|
return generateObjCToKotlinMethodAdapter(methodBridge, selector) {
|
||||||
initRuntimeIfNeeded() // For instance methods it gets called when allocating.
|
initRuntimeIfNeeded() // For instance methods it gets called when allocating.
|
||||||
|
|
||||||
val value = getObjectValue(context.ir.get(descriptor), ExceptionHandler.Caller, locationInfo = null)
|
val value = getObjectValue(context.ir.get(descriptor), shared = false, locationInfo = null, exceptionHandler = ExceptionHandler.Caller)
|
||||||
ret(kotlinToObjC(value, ReferenceBridge))
|
ret(kotlinToObjC(value, ReferenceBridge))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-7
@@ -372,17 +372,14 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
|
|
||||||
private val arrayGetSymbol = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
|
private val arrayGetSymbol = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||||
|
|
||||||
private val genericFreezeSymbol = context.ir.symbols.freeze
|
|
||||||
private val arrayType = context.builtIns.getArrayType(Variance.INVARIANT, irClass.defaultType)
|
private val arrayType = context.builtIns.getArrayType(Variance.INVARIANT, irClass.defaultType)
|
||||||
|
|
||||||
private fun createValuesPropertyInitializer(enumEntries: List<IrEnumEntry>): IrAnonymousInitializerImpl {
|
private fun createValuesPropertyInitializer(enumEntries: List<IrEnumEntry>): IrAnonymousInitializerImpl {
|
||||||
val startOffset = irClass.startOffset
|
val startOffset = irClass.startOffset
|
||||||
val endOffset = irClass.endOffset
|
val endOffset = irClass.endOffset
|
||||||
|
|
||||||
val symbol = IrAnonymousInitializerSymbolImpl(loweredEnum.implObject.descriptor)
|
return IrAnonymousInitializerImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, loweredEnum.implObject.descriptor).apply {
|
||||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody(irClass) {
|
||||||
return IrAnonymousInitializerImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, symbol).apply {
|
|
||||||
body = irBuilder.irBlockBody(irClass) {
|
|
||||||
val instances = irTemporary(irGetField(irGet(loweredEnum.implObject.thisReceiver!!.symbol), loweredEnum.valuesField.symbol))
|
val instances = irTemporary(irGetField(irGet(loweredEnum.implObject.thisReceiver!!.symbol), loweredEnum.valuesField.symbol))
|
||||||
enumEntries
|
enumEntries
|
||||||
.sortedBy { it.descriptor.name }
|
.sortedBy { it.descriptor.name }
|
||||||
@@ -398,8 +395,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
putValueArgument(1, initializer)
|
putValueArgument(1, initializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+irCall(genericFreezeSymbol, listOf(arrayType)).apply {
|
+irCall(this@EnumClassLowering.context.ir.symbols.freeze, listOf(arrayType)).apply {
|
||||||
extensionReceiver = irGet(instances.symbol)
|
extensionReceiver = irGet(loweredEnum.implObject.thisReceiver!!.symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1103,6 +1103,47 @@ OBJ_GETTER(InitInstance,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OBJ_GETTER(InitSharedInstance,
|
||||||
|
ObjHeader** location, const TypeInfo* type_info, void (*ctor)(ObjHeader*)) {
|
||||||
|
#if KONAN_NO_THREADS
|
||||||
|
return InitInstance(location, type_info, ctor);
|
||||||
|
#else
|
||||||
|
ObjHeader* initializing = reinterpret_cast<ObjHeader*>(1);
|
||||||
|
ObjHeader* value;
|
||||||
|
|
||||||
|
// Spin lock.
|
||||||
|
while ((value = __sync_val_compare_and_swap(location, nullptr, initializing)) == initializing);
|
||||||
|
if (value != nullptr) {
|
||||||
|
// OK'ish, inited by someone else.
|
||||||
|
RETURN_OBJ(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjHeader* object = AllocInstance(type_info, OBJ_RESULT);
|
||||||
|
MEMORY_LOG("Calling UpdateRef from InitInstance\n")
|
||||||
|
UpdateRef(location, object);
|
||||||
|
__sync_synchronize();
|
||||||
|
#if KONAN_NO_EXCEPTIONS
|
||||||
|
ctor(object);
|
||||||
|
// TODO: uncomment as soon as cycles are correctly handled during freezing.
|
||||||
|
//if (!object->container()->frozen())
|
||||||
|
//ThrowFreezingException();
|
||||||
|
return object;
|
||||||
|
#else
|
||||||
|
try {
|
||||||
|
ctor(object);
|
||||||
|
//if (!object->container()->frozen())
|
||||||
|
//ThrowFreezingException();
|
||||||
|
return object;
|
||||||
|
} catch (...) {
|
||||||
|
UpdateRef(OBJ_RESULT, nullptr);
|
||||||
|
UpdateRef(location, nullptr);
|
||||||
|
__sync_synchronize();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool HasReservedObjectTail(ObjHeader* obj) {
|
bool HasReservedObjectTail(ObjHeader* obj) {
|
||||||
return kObjectReservedTailSize != 0 && !obj->permanent();
|
return kObjectReservedTailSize != 0 && !obj->permanent();
|
||||||
}
|
}
|
||||||
@@ -1151,7 +1192,7 @@ void UpdateRef(ObjHeader** location, const ObjHeader* object) {
|
|||||||
AddRef(object);
|
AddRef(object);
|
||||||
}
|
}
|
||||||
*const_cast<const ObjHeader**>(location) = object;
|
*const_cast<const ObjHeader**>(location) = object;
|
||||||
if (old != nullptr) {
|
if (reinterpret_cast<uintptr_t>(old) > 1) {
|
||||||
ReleaseRef(old);
|
ReleaseRef(old);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,16 @@ fun <T> T.freeze(): T {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove.
|
||||||
|
fun <T> T.freezeAllowCycles(): T {
|
||||||
|
try {
|
||||||
|
freezeInternal(this)
|
||||||
|
} catch (t: FreezingException) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
val Any?.isFrozen
|
val Any?.isFrozen
|
||||||
get() = isFrozenInternal(this)
|
get() = isFrozenInternal(this)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user