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.
|
// for example.
|
||||||
var needsRuntimeInit = false
|
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 {
|
init {
|
||||||
irFunction?.let {
|
irFunction?.let {
|
||||||
if (!irFunction.isExported()) {
|
if (!irFunction.isExported()) {
|
||||||
@@ -1221,6 +1228,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
internal fun epilogue() {
|
internal fun epilogue() {
|
||||||
appendingTo(prologueBb) {
|
appendingTo(prologueBb) {
|
||||||
if (needsRuntimeInit) {
|
if (needsRuntimeInit) {
|
||||||
|
check(!forbidRuntime) { "Attempt to init runtime where runtime usage is forbidden" }
|
||||||
call(context.llvm.initRuntimeIfNeeded, emptyList())
|
call(context.llvm.initRuntimeIfNeeded, emptyList())
|
||||||
}
|
}
|
||||||
val slots = if (needSlotsPhi)
|
val slots = if (needSlotsPhi)
|
||||||
@@ -1228,6 +1236,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
else
|
else
|
||||||
kNullObjHeaderPtrPtr
|
kNullObjHeaderPtrPtr
|
||||||
if (needSlots) {
|
if (needSlots) {
|
||||||
|
check(!forbidRuntime) { "Attempt to start a frame where runtime usage is forbidden" }
|
||||||
// Zero-init slots.
|
// Zero-init slots.
|
||||||
val slotsMem = bitcast(kInt8Ptr, slots)
|
val slotsMem = bitcast(kInt8Ptr, slots)
|
||||||
call(context.llvm.memsetFunction,
|
call(context.llvm.memsetFunction,
|
||||||
@@ -1267,7 +1276,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
returnType == voidType -> {
|
returnType == voidType -> {
|
||||||
releaseVars()
|
releaseVars()
|
||||||
assert(returnSlot == null)
|
assert(returnSlot == null)
|
||||||
if (context.memoryModel == MemoryModel.EXPERIMENTAL)
|
if (!forbidRuntime && context.memoryModel == MemoryModel.EXPERIMENTAL)
|
||||||
call(context.llvm.Kotlin_mm_safePointFunctionEpilogue, emptyList())
|
call(context.llvm.Kotlin_mm_safePointFunctionEpilogue, emptyList())
|
||||||
LLVMBuildRetVoid(builder)
|
LLVMBuildRetVoid(builder)
|
||||||
}
|
}
|
||||||
@@ -1278,7 +1287,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
updateReturnRef(returnPhi, returnSlot!!)
|
updateReturnRef(returnPhi, returnSlot!!)
|
||||||
}
|
}
|
||||||
releaseVars()
|
releaseVars()
|
||||||
if (context.memoryModel == MemoryModel.EXPERIMENTAL)
|
if (!forbidRuntime && context.memoryModel == MemoryModel.EXPERIMENTAL)
|
||||||
call(context.llvm.Kotlin_mm_safePointFunctionEpilogue, emptyList())
|
call(context.llvm.Kotlin_mm_safePointFunctionEpilogue, emptyList())
|
||||||
LLVMBuildRet(builder, returnPhi)
|
LLVMBuildRet(builder, returnPhi)
|
||||||
}
|
}
|
||||||
@@ -1320,7 +1329,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
}
|
}
|
||||||
|
|
||||||
releaseVars()
|
releaseVars()
|
||||||
if (context.memoryModel == MemoryModel.EXPERIMENTAL)
|
if (!forbidRuntime && context.memoryModel == MemoryModel.EXPERIMENTAL)
|
||||||
call(context.llvm.Kotlin_mm_safePointExceptionUnwind, emptyList())
|
call(context.llvm.Kotlin_mm_safePointExceptionUnwind, emptyList())
|
||||||
LLVMBuildResume(builder, landingpad)
|
LLVMBuildResume(builder, landingpad)
|
||||||
}
|
}
|
||||||
@@ -1452,6 +1461,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
|
|
||||||
private fun releaseVars() {
|
private fun releaseVars() {
|
||||||
if (needSlots) {
|
if (needSlots) {
|
||||||
|
check(!forbidRuntime) { "Attempt to leave a frame where runtime usage is forbidden" }
|
||||||
call(context.llvm.leaveFrameFunction,
|
call(context.llvm.leaveFrameFunction,
|
||||||
listOf(slotsPhi!!, Int32(vars.skipSlots).llvm, Int32(slotCount).llvm))
|
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)
|
LLVMSetLinkage(ctorFunction, LLVMLinkage.LLVMPrivateLinkage)
|
||||||
generateFunction(codegen, ctorFunction) {
|
generateFunction(codegen, ctorFunction) {
|
||||||
|
forbidRuntime = true
|
||||||
call(context.llvm.appendToInitalizersTail, listOf(initNodePtr))
|
call(context.llvm.appendToInitalizersTail, listOf(initNodePtr))
|
||||||
ret(null)
|
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.
|
// Runtime is linked into stdlib module only, so import runtime global from it.
|
||||||
val global = codegen.importGlobal(name, value.llvmType, context.standardLlvmSymbolsOrigin)
|
val global = codegen.importGlobal(name, value.llvmType, context.standardLlvmSymbolsOrigin)
|
||||||
val initializer = generateFunction(codegen, functionType(voidType, false), "") {
|
val initializer = generateFunction(codegen, functionType(voidType, false), "") {
|
||||||
|
forbidRuntime = true
|
||||||
store(value.llvm, global)
|
store(value.llvm, global)
|
||||||
ret(null)
|
ret(null)
|
||||||
}
|
}
|
||||||
@@ -2519,6 +2521,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
private fun appendStaticInitializers(ctorFunction: LLVMValueRef, initializers: List<LLVMValueRef>) {
|
private fun appendStaticInitializers(ctorFunction: LLVMValueRef, initializers: List<LLVMValueRef>) {
|
||||||
generateFunction(codegen, ctorFunction) {
|
generateFunction(codegen, ctorFunction) {
|
||||||
|
forbidRuntime = true
|
||||||
val initGuardName = ctorFunction.name.orEmpty() + "_guard"
|
val initGuardName = ctorFunction.name.orEmpty() + "_guard"
|
||||||
val initGuard = LLVMAddGlobal(context.llvmModule, int32Type, initGuardName)
|
val initGuard = LLVMAddGlobal(context.llvmModule, int32Type, initGuardName)
|
||||||
LLVMSetInitializer(initGuard, kImmZero)
|
LLVMSetInitializer(initGuard, kImmZero)
|
||||||
@@ -2558,6 +2561,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
)
|
)
|
||||||
LLVMSetLinkage(globalCtorFunction, LLVMLinkage.LLVMPrivateLinkage)
|
LLVMSetLinkage(globalCtorFunction, LLVMLinkage.LLVMPrivateLinkage)
|
||||||
generateFunction(codegen, globalCtorFunction) {
|
generateFunction(codegen, globalCtorFunction) {
|
||||||
|
forbidRuntime = true
|
||||||
ctorFunctions.forEach {
|
ctorFunctions.forEach {
|
||||||
call(it, emptyList(), Lifetime.IRRELEVANT,
|
call(it, emptyList(), Lifetime.IRRELEVANT,
|
||||||
exceptionHandler = ExceptionHandler.Caller, verbatim = true)
|
exceptionHandler = ExceptionHandler.Caller, verbatim = true)
|
||||||
|
|||||||
+1
@@ -354,6 +354,7 @@ internal class ObjCExportCodeGenerator(
|
|||||||
if (externalGlobalInitializers.isEmpty()) return
|
if (externalGlobalInitializers.isEmpty()) return
|
||||||
|
|
||||||
val initializer = generateFunction(codegen, functionType(voidType, false), "initObjCExportGlobals") {
|
val initializer = generateFunction(codegen, functionType(voidType, false), "initObjCExportGlobals") {
|
||||||
|
forbidRuntime = true
|
||||||
externalGlobalInitializers.forEach { (global, value) ->
|
externalGlobalInitializers.forEach { (global, value) ->
|
||||||
store(value.llvm, global)
|
store(value.llvm, global)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user