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)
|
||||
|
||||
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()
|
||||
addFakeOverrides()
|
||||
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
|
||||
val indirectBranchesAreAllowed = target != KonanTarget.WASM32
|
||||
val threadsAreAllowed = (target != KonanTarget.WASM32) && (target !is KonanTarget.ZEPHYR)
|
||||
|
||||
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())
|
||||
|
||||
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(
|
||||
context.getInternalFunctions("getContinuation").single())
|
||||
|
||||
+8
-5
@@ -56,7 +56,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
descriptor.objectInstanceFieldSymbolName,
|
||||
llvmType,
|
||||
origin = descriptor.llvmSymbolOrigin,
|
||||
threadLocal = true
|
||||
threadLocal = !descriptor.symbol.objectIsShared
|
||||
)
|
||||
}
|
||||
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 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 icmpUGt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntUGT, arg0, arg1, name)!!
|
||||
|
||||
/* floating-point comparisons */
|
||||
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(
|
||||
descriptor: ClassDescriptor,
|
||||
shared: Boolean,
|
||||
exceptionHandler: ExceptionHandler,
|
||||
locationInfo: LocationInfo?
|
||||
): LLVMValueRef {
|
||||
@@ -578,15 +580,16 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
val bbInit = basicBlock("label_init", locationInfo)
|
||||
val bbExit = basicBlock("label_continue", locationInfo)
|
||||
val objectVal = loadSlot(objectPtr, false)
|
||||
val condition = icmpNe(objectVal, codegen.kNullObjHeaderPtr)
|
||||
val condition = icmpUGt(ptrToInt(objectVal, codegen.intPtrType), codegen.immOneIntPtrType)
|
||||
condBr(condition, bbExit, bbInit)
|
||||
|
||||
positionAtEnd(bbInit)
|
||||
val typeInfo = codegen.typeInfoForAllocation(descriptor)
|
||||
val initFunction = descriptor.constructors.first { it.valueParameters.size == 0 }
|
||||
val ctor = codegen.llvmFunction(initFunction)
|
||||
val defaultConstructor = descriptor.constructors.first { it.valueParameters.size == 0 }
|
||||
val ctor = codegen.llvmFunction(defaultConstructor)
|
||||
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
|
||||
br(bbExit)
|
||||
|
||||
|
||||
+1
@@ -398,6 +398,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||
val allocInstanceFunction = importRtFunction("AllocInstance")
|
||||
val allocArrayFunction = importRtFunction("AllocArrayInstance")
|
||||
val initInstanceFunction = importRtFunction("InitInstance")
|
||||
val initSharedInstanceFunction = importRtFunction("InitSharedInstance")
|
||||
val updateReturnRefFunction = importRtFunction("UpdateReturnRef")
|
||||
val updateRefFunction = importRtFunction("UpdateRef")
|
||||
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.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
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.symbols.*
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
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.isUnit
|
||||
|
||||
val IrClassSymbol.objectIsShared get() = owner.origin == DECLARATION_ORIGIN_ENUM
|
||||
|
||||
internal fun emitLLVM(context: Context) {
|
||||
val irModule = context.irModule!!
|
||||
|
||||
@@ -777,6 +776,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
private fun evaluateGetObjectValue(value: IrGetObjectValue): LLVMValueRef =
|
||||
functionGenerationContext.getObjectValue(
|
||||
value.symbol.owner,
|
||||
value.symbol.objectIsShared && context.config.threadsAreAllowed,
|
||||
currentCodeContext.exceptionHandler,
|
||||
value.startLocation
|
||||
)
|
||||
|
||||
+2
-1
@@ -313,8 +313,9 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
} else {
|
||||
"kobjref:" + qualifyInternalName(descriptor)
|
||||
}
|
||||
val threadLocal = !(descriptor.symbol.objectIsShared && context.config.threadsAreAllowed)
|
||||
val instanceFieldRef = addGlobal(
|
||||
symbolName, getLLVMType(descriptor.defaultType), isExported = isExported, threadLocal = true)
|
||||
symbolName, getLLVMType(descriptor.defaultType), isExported = isExported, threadLocal = threadLocal)
|
||||
|
||||
LLVMSetInitializer(instanceFieldRef, kNullObjHeaderPtr)
|
||||
|
||||
|
||||
+1
-1
@@ -924,7 +924,7 @@ private fun ObjCExportCodeGenerator.createObjectInstanceAdapter(
|
||||
return generateObjCToKotlinMethodAdapter(methodBridge, selector) {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
+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 genericFreezeSymbol = context.ir.symbols.freeze
|
||||
private val arrayType = context.builtIns.getArrayType(Variance.INVARIANT, irClass.defaultType)
|
||||
|
||||
private fun createValuesPropertyInitializer(enumEntries: List<IrEnumEntry>): IrAnonymousInitializerImpl {
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
|
||||
val symbol = IrAnonymousInitializerSymbolImpl(loweredEnum.implObject.descriptor)
|
||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||
return IrAnonymousInitializerImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, symbol).apply {
|
||||
body = irBuilder.irBlockBody(irClass) {
|
||||
return IrAnonymousInitializerImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, loweredEnum.implObject.descriptor).apply {
|
||||
body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody(irClass) {
|
||||
val instances = irTemporary(irGetField(irGet(loweredEnum.implObject.thisReceiver!!.symbol), loweredEnum.valuesField.symbol))
|
||||
enumEntries
|
||||
.sortedBy { it.descriptor.name }
|
||||
@@ -398,8 +395,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
putValueArgument(1, initializer)
|
||||
}
|
||||
}
|
||||
+irCall(genericFreezeSymbol, listOf(arrayType)).apply {
|
||||
extensionReceiver = irGet(instances.symbol)
|
||||
+irCall(this@EnumClassLowering.context.ir.symbols.freeze, listOf(arrayType)).apply {
|
||||
extensionReceiver = irGet(loweredEnum.implObject.thisReceiver!!.symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1103,6 +1103,47 @@ OBJ_GETTER(InitInstance,
|
||||
#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) {
|
||||
return kObjectReservedTailSize != 0 && !obj->permanent();
|
||||
}
|
||||
@@ -1151,7 +1192,7 @@ void UpdateRef(ObjHeader** location, const ObjHeader* object) {
|
||||
AddRef(object);
|
||||
}
|
||||
*const_cast<const ObjHeader**>(location) = object;
|
||||
if (old != nullptr) {
|
||||
if (reinterpret_cast<uintptr_t>(old) > 1) {
|
||||
ReleaseRef(old);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,16 @@ fun <T> T.freeze(): T {
|
||||
return this
|
||||
}
|
||||
|
||||
// TODO: Remove.
|
||||
fun <T> T.freezeAllowCycles(): T {
|
||||
try {
|
||||
freezeInternal(this)
|
||||
} catch (t: FreezingException) {
|
||||
return this
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
val Any?.isFrozen
|
||||
get() = isFrozenInternal(this)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user