[K/N] Fix cleaning stack-local primitive array

^KT-55984
This commit is contained in:
Pavel Kunyavskiy
2023-01-17 17:03:25 +01:00
committed by Space Team
parent 9f850c1179
commit 2843c0ad1e
16 changed files with 142 additions and 35 deletions
@@ -1173,6 +1173,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@Test
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@Test
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
+10
View File
@@ -0,0 +1,10 @@
// WITH_STDLIB
fun box() : String{
for (iter in 0 until 10) {
val destination = ByteArray(8)
if (destination[0] != 0.toByte()) return "FAIL"
destination[0] = 1
}
return "OK"
}
@@ -1065,6 +1065,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@Test
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@Test
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
@@ -1173,6 +1173,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@Test
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@Test
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
@@ -934,6 +934,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt594.kt");
@@ -549,6 +549,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@Test
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@Test
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
@@ -331,6 +331,12 @@ public class JsLegacyPrimitiveArraysBoxTestGenerated extends AbstractJsLegacyPri
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@Test
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@Test
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
@@ -603,6 +603,12 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@Test
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@Test
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
@@ -603,6 +603,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@Test
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@Test
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
@@ -603,6 +603,12 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@Test
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@Test
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
@@ -549,6 +549,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt594.kt");
@@ -238,20 +238,35 @@ private inline fun <T : FunctionGenerationContext> generateFunctionBody(
internal data class LocationInfoRange(var start: LocationInfo, var end: LocationInfo?)
internal interface StackLocalsManager {
fun alloc(irClass: IrClass, cleanFieldsExplicitly: Boolean): LLVMValueRef
fun alloc(irClass: IrClass): LLVMValueRef
fun allocArray(irClass: IrClass, count: LLVMValueRef): LLVMValueRef
fun clean(refsOnly: Boolean)
fun enterScope()
fun exitScope()
}
internal class StackLocalsManagerImpl(
val functionGenerationContext: FunctionGenerationContext,
val bbInitStackLocals: LLVMBasicBlockRef
) : StackLocalsManager {
private class StackLocal(val isArray: Boolean, val irClass: IrClass,
val bodyPtr: LLVMValueRef, val objHeaderPtr: LLVMValueRef,
val gcRootSetSlot: LLVMValueRef?)
private var scopeDepth = 0
override fun enterScope() { scopeDepth++ }
override fun exitScope() { scopeDepth-- }
private fun isRootScope() = scopeDepth == 0
private class StackLocal(
val arraySize: Int?,
val irClass: IrClass,
val stackAllocationPtr: LLVMValueRef,
val objHeaderPtr: LLVMValueRef,
val gcRootSetSlot: LLVMValueRef?
) {
val isArray
get() = arraySize != null
}
private val stackLocals = mutableListOf<StackLocal>()
@@ -260,7 +275,7 @@ internal class StackLocalsManagerImpl(
private fun FunctionGenerationContext.createRootSetSlot() =
if (context.memoryModel == MemoryModel.EXPERIMENTAL) alloca(kObjHeaderPtr) else null
override fun alloc(irClass: IrClass, cleanFieldsExplicitly: Boolean): LLVMValueRef = with(functionGenerationContext) {
override fun alloc(irClass: IrClass): LLVMValueRef = with(functionGenerationContext) {
val classInfo = llvmDeclarations.forClass(irClass)
val type = classInfo.bodyType
val stackLocal = appendingTo(bbInitStackLocals) {
@@ -273,12 +288,13 @@ internal class StackLocalsManagerImpl(
val typeInfo = codegen.typeInfoForAllocation(irClass)
setTypeInfoForLocalObject(objectHeader, typeInfo)
val gcRootSetSlot = createRootSetSlot()
StackLocal(false, irClass, stackSlot, objectHeader, gcRootSetSlot)
StackLocal(null, irClass, stackSlot, objectHeader, gcRootSetSlot)
}
stackLocals += stackLocal
if (cleanFieldsExplicitly)
if (!isRootScope()) {
clean(stackLocal, false)
}
if (stackLocal.gcRootSetSlot != null) {
storeStackRef(stackLocal.objHeaderPtr, stackLocal.gcRootSetSlot)
}
@@ -332,11 +348,14 @@ internal class StackLocalsManagerImpl(
constCount * LLVMSizeOfTypeInBits(codegen.llvmTargetData, arrayToElementType[irClass.symbol]).toInt() / 8
)
val gcRootSetSlot = createRootSetSlot()
StackLocal(true, irClass, arraySlot, arrayHeaderSlot, gcRootSetSlot)
StackLocal(constCount, irClass, arraySlot, arrayHeaderSlot, gcRootSetSlot)
}
stackLocals += stackLocal
val result = bitcast(kObjHeaderPtr, stackLocal.objHeaderPtr)
if (!isRootScope()) {
clean(stackLocal, false)
}
if (stackLocal.gcRootSetSlot != null) {
storeStackRef(result, stackLocal.gcRootSetSlot)
}
@@ -347,8 +366,14 @@ internal class StackLocalsManagerImpl(
private fun clean(stackLocal: StackLocal, refsOnly: Boolean) = with(functionGenerationContext) {
if (stackLocal.isArray) {
if (stackLocal.irClass.symbol == context.ir.symbols.array)
if (stackLocal.irClass.symbol == context.ir.symbols.array) {
call(llvm.zeroArrayRefsFunction, listOf(stackLocal.objHeaderPtr))
} else if (!refsOnly) {
memset(bitcast(llvm.int8PtrType, structGep(stackLocal.stackAllocationPtr, 1, "arrayBody")),
0,
stackLocal.arraySize!! * LLVMSizeOfTypeInBits(codegen.llvmTargetData, arrayToElementType[stackLocal.irClass.symbol]).toInt() / 8
)
}
} else {
val info = llvmDeclarations.forClass(stackLocal.irClass)
val type = info.bodyType
@@ -356,7 +381,7 @@ internal class StackLocalsManagerImpl(
val fieldType = LLVMStructGetTypeAtIndex(type, fieldIndex)!!
if (isObjectType(fieldType)) {
val fieldPtr = LLVMBuildStructGEP(builder, stackLocal.bodyPtr, fieldIndex, "")!!
val fieldPtr = LLVMBuildStructGEP(builder, stackLocal.stackAllocationPtr, fieldIndex, "")!!
if (refsOnly)
storeHeapRef(kNullObjHeaderPtr, fieldPtr)
else
@@ -365,7 +390,7 @@ internal class StackLocalsManagerImpl(
}
if (!refsOnly) {
val bodyPtr = ptrToInt(stackLocal.bodyPtr, codegen.intPtrType)
val bodyPtr = ptrToInt(stackLocal.stackAllocationPtr, codegen.intPtrType)
val bodySize = LLVMSizeOfTypeInBits(codegen.llvmTargetData, type).toInt() / 8
val serviceInfoSize = runtime.pointerSize
val serviceInfoSizeLlvm = LLVMConstInt(codegen.intPtrType, serviceInfoSize.toLong(), 1)!!
@@ -778,12 +803,9 @@ internal abstract class FunctionGenerationContext(
fun allocInstance(typeInfo: LLVMValueRef, lifetime: Lifetime, resultSlot: LLVMValueRef?) : LLVMValueRef =
call(llvm.allocInstanceFunction, listOf(typeInfo), lifetime, resultSlot = resultSlot)
fun allocInstance(irClass: IrClass, lifetime: Lifetime, stackLocalsManager: StackLocalsManager, resultSlot: LLVMValueRef?) =
fun allocInstance(irClass: IrClass, lifetime: Lifetime, resultSlot: LLVMValueRef?) =
if (lifetime == Lifetime.STACK)
stackLocalsManager.alloc(irClass,
// In case the allocation is not from the root scope, fields must be cleaned up explicitly,
// as the object might be being reused.
cleanFieldsExplicitly = stackLocalsManager != this.stackLocalsManager)
stackLocalsManager.alloc(irClass)
else
allocInstance(codegen.typeInfoForAllocation(irClass), lifetime, resultSlot)
@@ -117,8 +117,6 @@ internal interface IntrinsicGeneratorEnvironment {
val exceptionHandler: ExceptionHandler
val stackLocalsManager: StackLocalsManager
fun calculateLifetime(element: IrElement): Lifetime
fun evaluateCall(function: IrFunction, args: List<LLVMValueRef>, resultLifetime: Lifetime,
@@ -418,7 +416,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0]
val enumClass = callSite.getTypeArgument(typeParameterT)!!
val enumIrClass = enumClass.getClass()!!
return allocInstance(enumIrClass, environment.calculateLifetime(callSite), environment.stackLocalsManager, resultSlot)
return allocInstance(enumIrClass, environment.calculateLifetime(callSite), resultSlot)
}
private fun FunctionGenerationContext.emitGetPointerSize(): LLVMValueRef =
@@ -130,8 +130,6 @@ private interface CodeContext {
val exceptionHandler: ExceptionHandler
val stackLocalsManager: StackLocalsManager
/**
* Declares the variable.
* @return index of declared variable.
@@ -189,6 +187,16 @@ private interface CodeContext {
* Returns [DIScopeOpaqueRef] instance for corresponding scope.
*/
fun scope(): DIScopeOpaqueRef?
/**
* Called, when context is pushed on stack
*/
fun onEnter() {}
/**
* Called, when context is removed from stack
*/
fun onExit() {}
}
//-------------------------------------------------------------------------//
@@ -217,9 +225,6 @@ internal class CodeGeneratorVisitor(val generationState: NativeGenerationState,
override val exceptionHandler: ExceptionHandler
get() = currentCodeContext.exceptionHandler
override val stackLocalsManager: StackLocalsManager
get() = currentCodeContext.stackLocalsManager
override fun evaluateCall(function: IrFunction, args: List<LLVMValueRef>, resultLifetime: Lifetime, superClass: IrClass?, resultSlot: LLVMValueRef?) =
evaluateSimpleFunctionCall(function, args, resultLifetime, superClass, resultSlot)
@@ -256,8 +261,6 @@ internal class CodeGeneratorVisitor(val generationState: NativeGenerationState,
override val exceptionHandler get() = unsupported()
override val stackLocalsManager: StackLocalsManager get() = unsupported()
override fun genDeclareVariable(variable: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?) = unsupported(variable)
override fun getDeclaredValue(value: IrValueDeclaration) = -1
@@ -295,10 +298,12 @@ internal class CodeGeneratorVisitor(val generationState: NativeGenerationState,
val oldCodeContext = currentCodeContext
if (codeContext != null) {
currentCodeContext = codeContext
codeContext.onEnter()
}
try {
return block()
} finally {
codeContext?.onExit()
currentCodeContext = oldCodeContext
}
}
@@ -570,7 +575,16 @@ internal class CodeGeneratorVisitor(val generationState: NativeGenerationState,
//-------------------------------------------------------------------------//
private inner class LoopScope(val loop: IrLoop) : InnerScopeImpl() {
private open inner class StackLocalsScope() : InnerScopeImpl() {
override fun onEnter() {
functionGenerationContext.stackLocalsManager.enterScope()
}
override fun onExit() {
functionGenerationContext.stackLocalsManager.exitScope()
}
}
private inner class LoopScope(val loop: IrLoop) : StackLocalsScope() {
val loopExit = functionGenerationContext.basicBlock("loop_exit", loop.endLocation)
val loopCheck = functionGenerationContext.basicBlock("loop_check", loop.condition.startLocation)
@@ -587,9 +601,6 @@ internal class CodeGeneratorVisitor(val generationState: NativeGenerationState,
} else
super.genContinue(destination)
}
override val stackLocalsManager: StackLocalsManager =
object : StackLocalsManager by functionGenerationContext.stackLocalsManager { }
}
//-------------------------------------------------------------------------//
@@ -730,8 +741,6 @@ internal class CodeGeneratorVisitor(val generationState: NativeGenerationState,
override val exceptionHandler: ExceptionHandler
get() = ExceptionHandler.Caller
override val stackLocalsManager get() = functionGenerationContext.stackLocalsManager
override fun functionScope(): CodeContext = this
@@ -1326,7 +1335,6 @@ internal class CodeGeneratorVisitor(val generationState: NativeGenerationState,
functionGenerationContext.br(loopScope.loopCheck)
functionGenerationContext.positionAtEnd(loopScope.loopExit)
}
assert(loop.type.isUnit())
@@ -2490,8 +2498,7 @@ internal class CodeGeneratorVisitor(val generationState: NativeGenerationState,
constructedClass.isObjCClass() -> error("Call should've been lowered: ${callee.dump()}")
else -> functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee),
currentCodeContext.stackLocalsManager, resultSlot = resultSlot)
else -> functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee), resultSlot = resultSlot)
}
evaluateSimpleFunctionCall(callee.symbol.owner,
listOf(thisValue) + args, Lifetime.IRRELEVANT /* constructor doesn't return anything */)
@@ -641,6 +641,12 @@ public class K2NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTes
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@Test
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@Test
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
@@ -631,6 +631,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/arrays/kt503.kt");
}
@Test
@TestMetadata("kt55984.kt")
public void testKt55984() throws Exception {
runTest("compiler/testData/codegen/box/arrays/kt55984.kt");
}
@Test
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {