Do not generate safepoints for initializer functions (#4700)

This commit is contained in:
Alexander Shabalin
2021-02-15 10:25:28 +03:00
committed by Vasily Levchenko
parent 97262c273f
commit 05d4bbf367
3 changed files with 18 additions and 3 deletions
@@ -350,6 +350,13 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
// for example.
var needsRuntimeInit = false
// Marks that function is not allowed to call into Kotlin runtime. For this function no safepoints, no enter/leave
// frames are generated.
// TODO: Should forbid all calls into runtime except for explicitly allowed. Also should impose the same restriction
// on function being called from this one.
// TODO: Consider using a different abstraction than `FunctionGenerationContext`.
var forbidRuntime = false
init {
irFunction?.let {
if (!irFunction.isExported()) {
@@ -1221,6 +1228,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
internal fun epilogue() {
appendingTo(prologueBb) {
if (needsRuntimeInit) {
check(!forbidRuntime) { "Attempt to init runtime where runtime usage is forbidden" }
call(context.llvm.initRuntimeIfNeeded, emptyList())
}
val slots = if (needSlotsPhi)
@@ -1228,6 +1236,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
else
kNullObjHeaderPtrPtr
if (needSlots) {
check(!forbidRuntime) { "Attempt to start a frame where runtime usage is forbidden" }
// Zero-init slots.
val slotsMem = bitcast(kInt8Ptr, slots)
call(context.llvm.memsetFunction,
@@ -1267,7 +1276,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
returnType == voidType -> {
releaseVars()
assert(returnSlot == null)
if (context.memoryModel == MemoryModel.EXPERIMENTAL)
if (!forbidRuntime && context.memoryModel == MemoryModel.EXPERIMENTAL)
call(context.llvm.Kotlin_mm_safePointFunctionEpilogue, emptyList())
LLVMBuildRetVoid(builder)
}
@@ -1278,7 +1287,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
updateReturnRef(returnPhi, returnSlot!!)
}
releaseVars()
if (context.memoryModel == MemoryModel.EXPERIMENTAL)
if (!forbidRuntime && context.memoryModel == MemoryModel.EXPERIMENTAL)
call(context.llvm.Kotlin_mm_safePointFunctionEpilogue, emptyList())
LLVMBuildRet(builder, returnPhi)
}
@@ -1320,7 +1329,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
}
releaseVars()
if (context.memoryModel == MemoryModel.EXPERIMENTAL)
if (!forbidRuntime && context.memoryModel == MemoryModel.EXPERIMENTAL)
call(context.llvm.Kotlin_mm_safePointExceptionUnwind, emptyList())
LLVMBuildResume(builder, landingpad)
}
@@ -1452,6 +1461,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
private fun releaseVars() {
if (needSlots) {
check(!forbidRuntime) { "Attempt to leave a frame where runtime usage is forbidden" }
call(context.llvm.leaveFrameFunction,
listOf(slotsPhi!!, Int32(vars.skipSlots).llvm, Int32(slotCount).llvm))
}
@@ -513,6 +513,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
)
LLVMSetLinkage(ctorFunction, LLVMLinkage.LLVMPrivateLinkage)
generateFunction(codegen, ctorFunction) {
forbidRuntime = true
call(context.llvm.appendToInitalizersTail, listOf(initNodePtr))
ret(null)
}
@@ -2413,6 +2414,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
// Runtime is linked into stdlib module only, so import runtime global from it.
val global = codegen.importGlobal(name, value.llvmType, context.standardLlvmSymbolsOrigin)
val initializer = generateFunction(codegen, functionType(voidType, false), "") {
forbidRuntime = true
store(value.llvm, global)
ret(null)
}
@@ -2519,6 +2521,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
private fun appendStaticInitializers(ctorFunction: LLVMValueRef, initializers: List<LLVMValueRef>) {
generateFunction(codegen, ctorFunction) {
forbidRuntime = true
val initGuardName = ctorFunction.name.orEmpty() + "_guard"
val initGuard = LLVMAddGlobal(context.llvmModule, int32Type, initGuardName)
LLVMSetInitializer(initGuard, kImmZero)
@@ -2558,6 +2561,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
)
LLVMSetLinkage(globalCtorFunction, LLVMLinkage.LLVMPrivateLinkage)
generateFunction(codegen, globalCtorFunction) {
forbidRuntime = true
ctorFunctions.forEach {
call(it, emptyList(), Lifetime.IRRELEVANT,
exceptionHandler = ExceptionHandler.Caller, verbatim = true)
@@ -354,6 +354,7 @@ internal class ObjCExportCodeGenerator(
if (externalGlobalInitializers.isEmpty()) return
val initializer = generateFunction(codegen, functionType(voidType, false), "initObjCExportGlobals") {
forbidRuntime = true
externalGlobalInitializers.forEach { (global, value) ->
store(value.llvm, global)
}