Move main thread check to legacy mm (#4483)

This commit is contained in:
Alexander Shabalin
2020-10-30 11:14:01 +03:00
committed by Stanislav Erokhin
parent 14526e57bc
commit 8dc5b95337
8 changed files with 32 additions and 24 deletions
@@ -452,9 +452,9 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
call(context.llvm.freezeSubgraph, listOf(value), Lifetime.IRRELEVANT, exceptionHandler)
}
fun checkMainThread(exceptionHandler: ExceptionHandler) {
fun checkGlobalsAccessible(exceptionHandler: ExceptionHandler) {
if (context.memoryModel == MemoryModel.STRICT)
call(context.llvm.checkMainThread, emptyList(), Lifetime.IRRELEVANT, exceptionHandler)
call(context.llvm.checkGlobalsAccessible, emptyList(), Lifetime.IRRELEVANT, exceptionHandler)
}
private fun updateReturnRef(value: LLVMValueRef, address: LLVMValueRef) {
@@ -521,7 +521,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
val mutationCheck = importRtFunction("MutationCheck")
val checkLifetimesConstraint = importRtFunction("CheckLifetimesConstraint")
val freezeSubgraph = importRtFunction("FreezeSubgraph")
val checkMainThread = importRtFunction("CheckIsMainThread")
val checkGlobalsAccessible = importRtFunction("CheckGlobalsAccessible")
val kRefSharedHolderInitLocal = importRtFunction("KRefSharedHolder_initLocal")
val kRefSharedHolderInit = importRtFunction("KRefSharedHolder_init")
@@ -38,8 +38,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.module
internal enum class FieldStorageKind {
MAIN_THREAD,
SHARED,
GLOBAL, // In the old memory model these are only accessible from the "main" thread.
SHARED_FROZEN,
THREAD_LOCAL
}
@@ -55,12 +55,12 @@ internal val IrField.storageKind: FieldStorageKind get() {
val annotations = correspondingPropertySymbol?.owner?.annotations ?: annotations
return when {
annotations.hasAnnotation(KonanFqNames.threadLocal) -> FieldStorageKind.THREAD_LOCAL
!isFinal -> FieldStorageKind.MAIN_THREAD
annotations.hasAnnotation(KonanFqNames.sharedImmutable) -> FieldStorageKind.SHARED
!isFinal -> FieldStorageKind.GLOBAL
annotations.hasAnnotation(KonanFqNames.sharedImmutable) -> FieldStorageKind.SHARED_FROZEN
// TODO: simplify, once IR types are fully there.
(type.classifierOrNull?.owner as? IrAnnotationContainer)
?.annotations?.hasAnnotation(KonanFqNames.frozen) == true -> FieldStorageKind.SHARED
else -> FieldStorageKind.MAIN_THREAD
?.annotations?.hasAnnotation(KonanFqNames.frozen) == true -> FieldStorageKind.SHARED_FROZEN
else -> FieldStorageKind.GLOBAL
}
}
@@ -71,9 +71,9 @@ internal fun IrClass.storageKind(context: Context): ObjectStorageKind = when {
else -> ObjectStorageKind.SHARED
}
val IrField.isMainOnlyNonPrimitive get() = when {
val IrField.isGlobalNonPrimitive get() = when {
type.computePrimitiveBinaryTypeOrNull() != null -> false
else -> storageKind == FieldStorageKind.MAIN_THREAD
else -> storageKind == FieldStorageKind.GLOBAL
}
internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid {
@@ -423,7 +423,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
val address = context.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(
functionGenerationContext
)
if (irField.storageKind == FieldStorageKind.SHARED)
if (irField.storageKind == FieldStorageKind.SHARED_FROZEN)
freeze(initialization, currentCodeContext.exceptionHandler)
storeAny(initialization, address, false)
}
@@ -1573,8 +1573,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
if (value.symbol.owner.correspondingPropertySymbol?.owner?.isConst == true) {
evaluateConst(value.symbol.owner.initializer?.expression as IrConst<*>)
} else {
if (context.config.threadsAreAllowed && value.symbol.owner.isMainOnlyNonPrimitive) {
functionGenerationContext.checkMainThread(currentCodeContext.exceptionHandler)
if (context.config.threadsAreAllowed && value.symbol.owner.isGlobalNonPrimitive) {
functionGenerationContext.checkGlobalsAccessible(currentCodeContext.exceptionHandler)
}
val ptr = context.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress(
functionGenerationContext
@@ -1642,9 +1642,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
val globalAddress = context.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress(
functionGenerationContext
)
if (context.config.threadsAreAllowed && value.symbol.owner.storageKind == FieldStorageKind.MAIN_THREAD)
functionGenerationContext.checkMainThread(currentCodeContext.exceptionHandler)
if (value.symbol.owner.storageKind == FieldStorageKind.SHARED)
if (context.config.threadsAreAllowed && value.symbol.owner.storageKind == FieldStorageKind.GLOBAL)
functionGenerationContext.checkGlobalsAccessible(currentCodeContext.exceptionHandler)
if (value.symbol.owner.storageKind == FieldStorageKind.SHARED_FROZEN)
functionGenerationContext.freeze(valueToAssign, currentCodeContext.exceptionHandler)
functionGenerationContext.storeAny(valueToAssign, globalAddress, false)
}
@@ -641,6 +641,8 @@ struct MemoryState {
// A stack of initializing singletons.
KStdVector<std::pair<ObjHeader**, ObjHeader*>> initializingSingletons;
bool isMainThread = false;
#if COLLECT_STATISTIC
#define CONTAINER_ALLOC_STAT(state, size, container) state->statistic.incAlloc(size, container);
#define CONTAINER_DESTROY_STAT(state, container) \
@@ -2007,6 +2009,7 @@ MemoryState* initMemory() {
#if USE_CYCLIC_GC
cyclicInit();
#endif // USE_CYCLIC_GC
memoryState->isMainThread = true;
}
return memoryState;
}
@@ -3608,4 +3611,9 @@ void PerformFullGC() {
garbageCollect(::memoryState, true);
}
void CheckGlobalsAccessible() {
if (!::memoryState->isMainThread)
ThrowIncorrectDereferenceException();
}
} // extern "C"
@@ -41,4 +41,5 @@ void EnsureDeclarationsEmitted() {
ensureUsed(CheckLifetimesConstraint);
ensureUsed(FreezeSubgraph);
ensureUsed(FreezeSubgraph);
ensureUsed(CheckGlobalsAccessible);
}
@@ -254,6 +254,8 @@ bool IsForeignRefAccessible(ObjHeader* object, ForeignRefContext context);
// and there's nothing else keeping the object alive.
void AdoptReferenceFromSharedVariable(ObjHeader* object);
void CheckGlobalsAccessible();
#ifdef __cplusplus
}
#endif
@@ -69,7 +69,6 @@ KBoolean g_checkLeakedCleaners = KonanNeedDebugInfo;
constexpr RuntimeState* kInvalidRuntime = nullptr;
THREAD_LOCAL_VARIABLE RuntimeState* runtimeState = kInvalidRuntime;
THREAD_LOCAL_VARIABLE int isMainThread = 0;
inline bool isValidRuntime() {
return ::runtimeState != kInvalidRuntime;
@@ -88,7 +87,6 @@ RuntimeState* initRuntime() {
bool firstRuntime = atomicAdd(&aliveRuntimesCount, 1) == 1;
// Keep global variables in state as well.
if (firstRuntime) {
isMainThread = 1;
konan::consoleInit();
#if KONAN_OBJC_INTEROP
Kotlin_ObjCExport_initialize();
@@ -151,11 +149,6 @@ void Kotlin_deinitRuntimeIfNeeded() {
}
}
void CheckIsMainThread() {
if (!isMainThread)
ThrowIncorrectDereferenceException();
}
KInt Konan_Platform_canAccessUnaligned() {
#if KONAN_NO_UNALIGNED_ACCESS
return 0;
@@ -234,4 +234,8 @@ void AdoptReferenceFromSharedVariable(ObjHeader* object) {
RuntimeCheck(false, "Unimplemented");
}
void CheckGlobalsAccessible() {
// Globals are always accessible.
}
} // extern "C"