Supported shared access to enums

This commit is contained in:
Igor Chevdar
2018-03-20 17:04:01 +03:00
parent 8477f79d58
commit 7227c5d100
11 changed files with 75 additions and 21 deletions
@@ -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))
@@ -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)!!
@@ -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())
@@ -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)
@@ -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")
@@ -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
)
@@ -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)
@@ -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))
}
}
@@ -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)
}
}
}
+42 -1
View File
@@ -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)