diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt index 0d17167d9dc..a8d697f8a7f 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt @@ -99,6 +99,8 @@ internal class NativeGenerationState( val cStubsManager = CStubsManager(config.target, this) lateinit var llvmDeclarations: LlvmDeclarations + val virtualFunctionTrampolines = mutableMapOf() + val coverage by lazy { CoverageManager(this) } lateinit var objCExport: ObjCExport diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cexport/CAdapterCodegen.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cexport/CAdapterCodegen.kt index 5fb8a522588..3b4d1ae4f6c 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cexport/CAdapterCodegen.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cexport/CAdapterCodegen.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrEnumEntry import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.util.isOverridable import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -49,11 +50,8 @@ internal class CAdapterCodegen( val bridgeFunctionProto = signature.toProto(cname, null, LLVMLinkage.LLVMExternalLinkage) // If function is virtual, we need to resolve receiver properly. generateFunction(codegen, bridgeFunctionProto) { - val callee = if (!DescriptorUtils.isTopLevelDeclaration(function) && - irFunction.isOverridable - ) { - val receiver = param(0) - lookupVirtualImpl(receiver, irFunction) + val callee = if (!DescriptorUtils.isTopLevelDeclaration(function) && irFunction.isOverridable) { + codegen.getVirtualFunctionTrampoline(irFunction as IrSimpleFunction) } else { // KT-45468: Alias insertion may not be handled by LLVM properly, in case callee is in the cache. // Hence, insert not an alias but a wrapper, hoping it will be optimized out later. diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index d4b7cf7f16a..cb0d6de394f 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.cgen.CBridgeOrigin import org.jetbrains.kotlin.backend.konan.descriptors.ClassGlobalHierarchyInfo import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.llvm.KonanBinaryInterface.symbolName import org.jetbrains.kotlin.backend.konan.llvm.ThreadState.Native import org.jetbrains.kotlin.backend.konan.llvm.ThreadState.Runnable import org.jetbrains.kotlin.backend.konan.llvm.objc.* @@ -116,6 +117,7 @@ internal inline fun generateFunction( startLocation, endLocation, switchToRunnable = isCToKotlinBridge, + needSafePoint = true, function) if (isCToKotlinBridge) { @@ -147,6 +149,7 @@ internal inline fun generateFunction( startLocation: LocationInfo? = null, endLocation: LocationInfo? = null, switchToRunnable: Boolean = false, + needSafePoint: Boolean = true, code: FunctionGenerationContext.() -> Unit ) : LlvmCallable { val function = codegen.addFunction(functionProto) @@ -155,7 +158,8 @@ internal inline fun generateFunction( codegen, startLocation, endLocation, - switchToRunnable = switchToRunnable + switchToRunnable = switchToRunnable, + needSafePoint = needSafePoint ) try { generateFunctionBody(functionGenerationContext, code) @@ -172,7 +176,8 @@ internal inline fun generateFunctionNoRuntime( code: FunctionGenerationContext.() -> Unit, ) : LlvmCallable { val function = codegen.addFunction(functionProto) - val functionGenerationContext = DefaultFunctionGenerationContext(function, codegen, null, null, switchToRunnable = false) + val functionGenerationContext = DefaultFunctionGenerationContext(function, codegen, null, null, + switchToRunnable = false, needSafePoint = true) try { functionGenerationContext.forbidRuntime = true require(!functionGenerationContext.isObjectType(functionGenerationContext.returnType!!)) { @@ -197,6 +202,134 @@ private inline fun generateFunctionBody( functionGenerationContext.resetDebugLocation() } +private fun IrSimpleFunction.findOverriddenMethodOfAny(): IrSimpleFunction? { + if (modality == Modality.ABSTRACT) return null + val resolved = resolveFakeOverride()!! + if ((resolved.parent as IrClass).isAny()) { + return resolved + } + + return null +} + +internal object VirtualTablesLookup { + fun FunctionGenerationContext.getInterfaceTableRecord(typeInfo: LLVMValueRef, interfaceId: Int): LLVMValueRef { + val interfaceTableSize = load(structGep(typeInfo, 9 /* interfaceTableSize_ */)) + val interfaceTable = load(structGep(typeInfo, 10 /* interfaceTable_ */)) + + fun fastPath(): LLVMValueRef { + // The fastest optimistic version. + val interfaceTableIndex = and(interfaceTableSize, llvm.int32(interfaceId)) + return gep(interfaceTable, interfaceTableIndex) + } + + // See details in ClassLayoutBuilder. + return if (context.ghaEnabled() + && context.globalHierarchyAnalysisResult.bitsPerColor <= ClassGlobalHierarchyInfo.MAX_BITS_PER_COLOR + && context.config.produce != CompilerOutputKind.FRAMEWORK + ) { + // All interface tables are small and no unknown interface inheritance. + fastPath() + } else { + val startLocationInfo = position()?.start + val fastPathBB = basicBlock("fast_path", startLocationInfo) + val slowPathBB = basicBlock("slow_path", startLocationInfo) + val takeResBB = basicBlock("take_res", startLocationInfo) + condBr(icmpGe(interfaceTableSize, llvm.kImmInt32Zero), fastPathBB, slowPathBB) + positionAtEnd(takeResBB) + val resultPhi = phi(pointerType(runtime.interfaceTableRecordType)) + appendingTo(fastPathBB) { + val fastValue = fastPath() + br(takeResBB) + addPhiIncoming(resultPhi, currentBlock to fastValue) + } + appendingTo(slowPathBB) { + val actualInterfaceTableSize = sub(llvm.kImmInt32Zero, interfaceTableSize) // -interfaceTableSize + val slowValue = call(llvm.lookupInterfaceTableRecord, + listOf(interfaceTable, actualInterfaceTableSize, llvm.int32(interfaceId))) + br(takeResBB) + addPhiIncoming(resultPhi, currentBlock to slowValue) + } + resultPhi + } + } + + fun FunctionGenerationContext.getVirtualImpl(receiver: LLVMValueRef, irFunction: IrSimpleFunction): LlvmCallable { + assert(LLVMTypeOf(receiver) == codegen.kObjHeaderPtr) + + val typeInfoPtr: LLVMValueRef = if (irFunction.getObjCMethodInfo() != null) + call(llvm.getObjCKotlinTypeInfo, listOf(receiver)) + else + loadTypeInfo(receiver) + + assert(typeInfoPtr.type == codegen.kTypeInfoPtr) { llvmtype2string(typeInfoPtr.type) } + + val owner = irFunction.parentAsClass + val canCallViaVtable = !owner.isInterface + val layoutBuilder = generationState.context.getLayoutBuilder(owner) + + val llvmMethod = when { + canCallViaVtable -> { + val index = layoutBuilder.vtableIndex(irFunction) + val vtablePlace = gep(typeInfoPtr, llvm.int32(1)) // typeInfoPtr + 1 + val vtable = bitcast(llvm.int8PtrPtrType, vtablePlace) + val slot = gep(vtable, llvm.int32(index)) + load(slot) + } + + else -> { + // Essentially: typeInfo.itable[place(interfaceId)].vtable[method] + val itablePlace = layoutBuilder.itablePlace(irFunction) + val interfaceTableRecord = getInterfaceTableRecord(typeInfoPtr, itablePlace.interfaceId) + load(gep(load(structGep(interfaceTableRecord, 2 /* vtable */)), llvm.int32(itablePlace.methodIndex))) + } + } + val functionPtrType = pointerType(codegen.getLlvmFunctionType(irFunction)) + return LlvmCallable( + bitcast(functionPtrType, llvmMethod), + LlvmFunctionSignature(irFunction, this) + ) + } +} + +/* + * Special trampoline function to call actual virtual implementation. This helps with reducing + * dependence between klibs/files (if vtable/itable of some class has changed, the call sites + * would be the same and wouldn't need recompiling). + */ +internal fun CodeGenerator.getVirtualFunctionTrampoline(irFunction: IrSimpleFunction): LlvmCallable { + /* + * Resolve owner of the call with special handling of Any methods: + * if toString/eq/hc is invoked on an interface instance, we resolve + * owner as Any and dispatch it via vtable. + */ + val anyMethod = irFunction.findOverriddenMethodOfAny() + return getVirtualFunctionTrampolineImpl(anyMethod ?: irFunction) +} + +private fun CodeGenerator.getVirtualFunctionTrampolineImpl(irFunction: IrSimpleFunction) = + generationState.virtualFunctionTrampolines.getOrPut(irFunction) { + val targetName = if (irFunction.isExported()) + irFunction.symbolName + else + irFunction.computePrivateSymbolName(irFunction.parentAsClass.fqNameForIrSerialization.asString()) + val proto = LlvmFunctionProto( + name = "$targetName-trampoline", + signature = LlvmFunctionSignature(irFunction, this), + origin = null, + linkage = linkageOf(irFunction) + ) + if (isExternal(irFunction)) + llvm.externalFunction(proto) + else generateFunction(this, proto, needSafePoint = false) { + val args = proto.signature.parameterTypes.indices.map { param(it) } + val receiver = param(0) + val callee = with(VirtualTablesLookup) { getVirtualImpl(receiver, irFunction) } + val result = call(callee, args, exceptionHandler = ExceptionHandler.Caller, verbatim = true) + ret(result) + } + } + /** * There're cases when we don't need end position or it is meaningless. */ @@ -390,6 +523,7 @@ internal abstract class FunctionGenerationContextBuilder { - // If this is a virtual method of the class - we can call via vtable. - val index = context.getLayoutBuilder(owner).vtableIndex(anyMethod ?: irFunction) - val vtablePlace = gep(typeInfoPtr, llvm.int32(1)) // typeInfoPtr + 1 - val vtable = bitcast(llvm.int8PtrPtrType, vtablePlace) - val slot = gep(vtable, llvm.int32(index)) - load(slot) - } - - else -> { - // Essentially: typeInfo.itable[place(interfaceId)].vtable[method] - val itablePlace = context.getLayoutBuilder(owner).itablePlace(irFunction) - val interfaceTableRecord = lookupInterfaceTableRecord(typeInfoPtr, itablePlace.interfaceId) - load(gep(load(structGep(interfaceTableRecord, 2 /* vtable */)), llvm.int32(itablePlace.methodIndex))) - } - } - val functionPtrType = pointerType(codegen.getLlvmFunctionType(irFunction)) - return LlvmCallable( - bitcast(functionPtrType, llvmMethod), - LlvmFunctionSignature(irFunction, this) - ) - } - - private fun IrSimpleFunction.findOverriddenMethodOfAny(): IrSimpleFunction? { - if (modality == Modality.ABSTRACT) return null - val resolved = resolveFakeOverride()!! - if ((resolved.parent as IrClass).isAny()) { - return resolved - } - - return null - } - @Suppress("UNUSED_PARAMETER") fun getObjectValue(irClass: IrClass, exceptionHandler: ExceptionHandler, startLocationInfo: LocationInfo?, endLocationInfo: LocationInfo? = null, @@ -1279,7 +1326,7 @@ internal abstract class FunctionGenerationContext( currentPositionHolder.resetBuilderDebugLocation() } - private fun position() = basicBlockToLastLocation[currentBlock] + fun position() = basicBlockToLastLocation[currentBlock] internal fun mapParameterForDebug(index: Int, value: LLVMValueRef) { appendingTo(localsInitBb) { @@ -1366,7 +1413,7 @@ internal abstract class FunctionGenerationContext( } else { check(!setCurrentFrameIsCalled) } - if (context.memoryModel == MemoryModel.EXPERIMENTAL && !forbidRuntime) { + if (context.memoryModel == MemoryModel.EXPERIMENTAL && !forbidRuntime && needSafePoint) { call(llvm.Kotlin_mm_safePointFunctionPrologue, emptyList()) } resetDebugLocation() @@ -1572,6 +1619,7 @@ internal class DefaultFunctionGenerationContext( startLocation: LocationInfo?, endLocation: LocationInfo?, switchToRunnable: Boolean, + needSafePoint: Boolean, irFunction: IrFunction? = null ) : FunctionGenerationContext( function, @@ -1579,6 +1627,7 @@ internal class DefaultFunctionGenerationContext( startLocation, endLocation, switchToRunnable, + needSafePoint, irFunction ) { // Note: return handling can be extracted to a separate class. diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index f6eb976763c..354d9538aa5 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -162,6 +162,13 @@ internal interface ContextUtils : RuntimeAware { return !generationState.llvmModuleSpecification.containsDeclaration(declaration) } + fun linkageOf(irFunction: IrFunction) = when { + isExternal(irFunction) -> LLVMLinkage.LLVMExternalLinkage + irFunction.isExported() -> LLVMLinkage.LLVMExternalLinkage + context.config.producePerFileCache && irFunction in generationState.calledFromExportedInlineFunctions -> LLVMLinkage.LLVMExternalLinkage + else -> LLVMLinkage.LLVMInternalLinkage + } + /** * LLVM function generated from the Kotlin function. * It may be declared as external function prototype. diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index f6d8641eb73..8ec77f6bc95 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -784,9 +784,16 @@ internal class CodeGeneratorVisitor( } } + private fun buildVirtualFunctionTrampoline(irFunction: IrSimpleFunction) { + codegen.getVirtualFunctionTrampoline(irFunction) + } + override fun visitFunction(declaration: IrFunction) { context.log{"visitFunction : ${ir2string(declaration)}"} + if (declaration is IrSimpleFunction && declaration.isOverridable && declaration.origin !is DECLARATION_ORIGIN_BRIDGE_METHOD) + buildVirtualFunctionTrampoline(declaration) + val scopeState = llvm.initializersGenerationState.scopeState if (declaration.origin == DECLARATION_ORIGIN_STATIC_GLOBAL_INITIALIZER) { require(scopeState.globalInitFunction == null) { "There can only be at most one global file initializer" } @@ -1597,7 +1604,8 @@ internal class CodeGeneratorVisitor( val interfaceId = dstHierarchyInfo.interfaceId val typeInfo = functionGenerationContext.loadTypeInfo(srcObjInfoPtr) with(functionGenerationContext) { - val interfaceTableRecord = lookupInterfaceTableRecord(typeInfo, interfaceId) + + val interfaceTableRecord = with(VirtualTablesLookup) { getInterfaceTableRecord(typeInfo, interfaceId) } icmpEq(load(structGep(interfaceTableRecord, 0 /* id */)), llvm.int32(interfaceId)) } } @@ -2617,8 +2625,8 @@ internal class CodeGeneratorVisitor( //-------------------------------------------------------------------------// - fun callVirtual(function: IrFunction, args: List, resultLifetime: Lifetime, resultSlot: LLVMValueRef?): LLVMValueRef { - val functionDeclarations = functionGenerationContext.lookupVirtualImpl(args.first(), function) + fun callVirtual(function: IrSimpleFunction, args: List, resultLifetime: Lifetime, resultSlot: LLVMValueRef?): LLVMValueRef { + val functionDeclarations = codegen.getVirtualFunctionTrampoline(function) return call(function, functionDeclarations, args, resultLifetime, resultSlot) } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt index 90aea26deef..efdf146ddbd 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt @@ -392,12 +392,7 @@ private class DeclarationsGeneratorVisitor(override val generationState: NativeG } } - val linkage = when { - declaration.isExported() -> LLVMLinkage.LLVMExternalLinkage - context.config.producePerFileCache && declaration in generationState.calledFromExportedInlineFunctions -> LLVMLinkage.LLVMExternalLinkage - else -> LLVMLinkage.LLVMInternalLinkage - } - val proto = LlvmFunctionProto(declaration, symbolName, this, linkage) + val proto = LlvmFunctionProto(declaration, symbolName, this, linkageOf(declaration)) context.log { "Creating llvm function ${symbolName} for ${declaration.render()}" } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt index 21c92b7d731..09315354d20 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt @@ -294,7 +294,7 @@ internal class BlockGenerator(private val codegen: CodeGenerator) { val invokeMethod = context.ir.symbols.functionN(numberOfParameters).owner.simpleFunctions() .single { it.name == OperatorNameConventions.INVOKE } - val llvmDeclarations = lookupVirtualImpl(kotlinFunction, invokeMethod) + val llvmDeclarations = codegen.getVirtualFunctionTrampoline(invokeMethod) val result = callFromBridge(llvmDeclarations, listOf(kotlinFunction) + kotlinArguments, Lifetime.ARGUMENT) if (bridge.returnsVoid) { ret(null) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index 23a7c8f2ac9..638997a7412 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -945,10 +945,10 @@ private fun ObjCExportCodeGenerator.generateObjCImp( listOf(param(0), codegen.typeInfoValue(target.parent as IrClass)) ) } - val llvmCallable = if (!isVirtual) { - codegen.llvmFunction(target) + val llvmCallable = if (isVirtual) { + codegen.getVirtualFunctionTrampoline(target as IrSimpleFunction) } else { - lookupVirtualImpl(args.first(), target) + codegen.llvmFunction(target) } call(llvmCallable, args, resultLifetime, exceptionHandler) } diff --git a/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.swift b/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.swift index 19124148846..25b20929c48 100644 --- a/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.swift +++ b/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.swift @@ -14,7 +14,7 @@ func testDirectObjc2Kotlin() throws { func testVirtualObjc2Kotlin() throws { let trace = StacktraceBridgesKt.createBar().foo() - try assertTrue(trace[5].contains("objc2kotlin_virtual_kfun:Foo#foo(){}kotlin.collections.List")) + try assertTrue(trace[6].contains("objc2kotlin_virtual_kfun:Foo#foo(){}kotlin.collections.List")) } func testKotlin2Objc() throws { diff --git a/native/native.tests/testData/lldb/kt42208.txt b/native/native.tests/testData/lldb/kt42208.txt index 9b83087dd0a..5679f3e68a5 100644 --- a/native/native.tests/testData/lldb/kt42208.txt +++ b/native/native.tests/testData/lldb/kt42208.txt @@ -6,9 +6,10 @@ frame #1: [..]`kfun:[..]main$lambda$0[..] at kt42208-2.kt:10:18 frame #2: [..]`kfun:$main$lambda$0$FUNCTION_REFERENCE$0[..]invoke[..](_this=[..])[..] at kt42208-1.kt:7:60 frame #3: [..]`kfun:$main$lambda$0$FUNCTION_REFERENCE$0.[..]$invoke(_this=[..]){}kotlin.Nothing[..] at kt42208-1.kt:7:60 - frame #4: [..]`kfun:#main(){} at kt42208-1.kt:5:5 - frame #5: [..]`Konan_start(args=[..]) at [..] - frame #6: [..] + frame #4: [..]`kfun:kotlin.Function0#invoke(){}1:0-trampoline + 73 + frame #5: [..]`kfun:#main(){} at kt42208-1.kt:5:5 + frame #6: [..]`Konan_start(args=[..]) at [..] frame #7: [..] + frame #8: [..] > q diff --git a/native/native.tests/testData/lldb/kt42208WithPassingLambdaToAnotherFunction.txt b/native/native.tests/testData/lldb/kt42208WithPassingLambdaToAnotherFunction.txt index 2b658d0cf3a..cfa42f3a556 100644 --- a/native/native.tests/testData/lldb/kt42208WithPassingLambdaToAnotherFunction.txt +++ b/native/native.tests/testData/lldb/kt42208WithPassingLambdaToAnotherFunction.txt @@ -5,8 +5,9 @@ * frame #0: [..]`kfun:[..]main$lambda$0[..] at kt42208-2.kt:14:5 frame #1: [..]`kfun:$main$lambda$0$FUNCTION_REFERENCE$0.[..]invoke[..](_this=[..])[..] at kt42208-1.kt:9:82 frame #2: [..]`kfun:$main$lambda$0$FUNCTION_REFERENCE$0.[..]$invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-1.kt:9:82 - frame #3: [..]`kfun:#bar(v=[..]){} at kt42208-3.kt:18:5 - frame #4: [..]`kfun:#main(){} at kt42208-1.kt:7:5 - frame #5: [..]`Konan_start(args=[..]) at [..] + frame #3: [..]`kfun:kotlin.Function0#invoke(){}1:0-trampoline + 73 + frame #4: [..]`kfun:#bar(v=[..]){} at kt42208-3.kt:18:5 + frame #5: [..]`kfun:#main(){} at kt42208-1.kt:7:5 + frame #6: [..]`Konan_start(args=[..]) at [..] > c > q diff --git a/native/native.tests/testData/lldb/kt42208WithVariable.txt b/native/native.tests/testData/lldb/kt42208WithVariable.txt index c59ffd53285..7200bccc978 100644 --- a/native/native.tests/testData/lldb/kt42208WithVariable.txt +++ b/native/native.tests/testData/lldb/kt42208WithVariable.txt @@ -5,23 +5,26 @@ * frame #0: [..]`kfun:[..]main$lambda$0[..] at kt42208-2.kt:15:5 frame #1: [..]`kfun:$main$lambda$0$FUNCTION_REFERENCE$0[..]invoke[..](_this=[..])[..] at kt42208-1.kt:10:71 frame #2: [..]`kfun:$main$lambda$0$FUNCTION_REFERENCE$0.[..]$invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-1.kt:10:71 - frame #3: [..]`kfun:#main(){} at kt42208-1.kt:6:5 - frame #4: [..]`Konan_start(args=[..]) at [..] - frame #5: [..] + frame #3: [..]`kfun:kotlin.Function0#invoke(){}1:0-trampoline + 73 + frame #4: [..]`kfun:#main(){} at kt42208-1.kt:6:5 + frame #5: [..]`Konan_start(args=[..]) at [..] + frame #6: [..] > c > bt * thread #1, [..] stop reason = breakpoint 1.1 * frame #0: [..]`kfun:[..]main$lambda$0[..] at kt42208-2.kt:15:5 frame #1: [..]`kfun:$main$lambda$0$FUNCTION_REFERENCE$0[..]invoke[..](_this=[..])[..] at kt42208-1.kt:10:71 frame #2: [..]`kfun:$main$lambda$0$FUNCTION_REFERENCE$0.[..]$invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-1.kt:10:71 - frame #3: [..]`kfun:#main(){} at kt42208-1.kt:7:5 - frame #4: [..]`Konan_start(args=[..]) at [..] + frame #3: [..]`kfun:kotlin.Function0#invoke(){}1:0-trampoline + 73 + frame #4: [..]`kfun:#main(){} at kt42208-1.kt:7:5 + frame #5: [..]`Konan_start(args=[..]) at [..] > c > bt * thread #1, [..] stop reason = breakpoint 1.1 * frame #0: [..]`kfun:[..]main$lambda$0[..] at kt42208-2.kt:15:5 frame #1: [..]`kfun:$main$lambda$0$FUNCTION_REFERENCE$0[..]invoke[..](_this=[..])[..] at kt42208-1.kt:10:71 frame #2: [..]`kfun:$main$lambda$0$FUNCTION_REFERENCE$0.[..]$invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-1.kt:10:71 - frame #3: [..]`kfun:#main(){} at kt42208-1.kt:8:5 - frame #4: [..]`Konan_start(args=[..]) at [..] + frame #3: [..]`kfun:kotlin.Function0#invoke(){}1:0-trampoline + 73 + frame #4: [..]`kfun:#main(){} at kt42208-1.kt:8:5 + frame #5: [..]`Konan_start(args=[..]) at [..] > q