Do not generate safepoints for initializer functions (#4700)
This commit is contained in:
committed by
Vasily Levchenko
parent
97262c273f
commit
05d4bbf367
+13
-3
@@ -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))
|
||||
}
|
||||
|
||||
+4
@@ -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)
|
||||
|
||||
+1
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user