From 61a19e0ccfc4ccb0aeb82405098e809f6fc19275 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Wed, 31 Jul 2019 11:36:32 +0300 Subject: [PATCH] Fix skipping top stack frames in optimized -Xg0 binaries Also do some refactoring. --- .../kotlin/backend/konan/llvm/ContextUtils.kt | 3 +- .../backend/konan/llvm/LlvmAttributes.kt | 34 +++++++++++++++++++ .../backend/konan/llvm/LlvmDeclarations.kt | 6 ++-- .../kotlin/backend/konan/llvm/LlvmUtils.kt | 34 +++++++++++++++---- runtime/src/main/cpp/Exceptions.cpp | 6 ++-- runtime/src/main/cpp/Natives.cpp | 4 --- 6 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmAttributes.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index d24392e0bd9..6c69f74f8a5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -312,8 +312,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { val result = LLVMAddFunction(llvmModule, name, type)!! attributes.forEach { val kindId = getLlvmAttributeKindId(it) - val attribute = LLVMCreateEnumAttribute(LLVMGetTypeContext(type), kindId, 0)!! - LLVMAddAttributeAtIndex(result, LLVMAttributeFunctionIndex, attribute) + addLlvmFunctionEnumAttribute(result, kindId) } return result } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmAttributes.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmAttributes.kt new file mode 100644 index 00000000000..cc3338f0a70 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmAttributes.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.LLVMValueRef +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.types.isNothing +import org.jetbrains.kotlin.ir.util.isThrowable + +internal fun addLlvmAttributes(context: Context, irFunction: IrFunction, llvmFunction: LLVMValueRef) { + if (irFunction.returnType.isNothing()) { + setFunctionNoReturn(llvmFunction) + } + + if (mustNotInline(context, irFunction)) { + setFunctionNoInline(llvmFunction) + } +} + +private fun mustNotInline(context: Context, irFunction: IrFunction): Boolean { + if (context.shouldContainLocationDebugInfo()) { + if (irFunction is IrConstructor && irFunction.isPrimary && irFunction.returnType.isThrowable()) { + // To simplify skipping this constructor when scanning call stack in Kotlin_getCurrentStackTrace. + return true + } + } + + return false +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt index 581a41040b0..bf313381b21 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt @@ -12,7 +12,6 @@ import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.types.isNothing import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -366,8 +365,9 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : "kfun:" + qualifyInternalName(declaration) } val function = LLVMAddFunction(context.llvmModule, symbolName, llvmFunctionType)!! - if (declaration.returnType.isNothing()) - setFunctionNoReturn(function) + + addLlvmAttributes(context, declaration, function) + function } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt index 356696bc7ac..067a39594f2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt @@ -284,37 +284,57 @@ private val noreturnAttrKindId by lazy { getLlvmAttributeKindId("noreturn") } +private val noinlineAttrKindId by lazy { + getLlvmAttributeKindId("noinline") +} + private val signextAttrKindId by lazy { getLlvmAttributeKindId("signext") } fun isFunctionNoUnwind(function: LLVMValueRef): Boolean { - val attribute = LLVMGetEnumAttributeAtIndex(function, LLVMAttributeFunctionIndex, nounwindAttrKindId) + val attribute = LLVMGetEnumAttributeAtIndex(function, LLVMAttributeFunctionIndex, nounwindAttrKindId.value) return attribute != null } -internal fun getLlvmAttributeKindId(attributeName: String): Int { +internal fun getLlvmAttributeKindId(attributeName: String): LLVMAttributeKindId { val attrKindId = LLVMGetEnumAttributeKindForName(attributeName, attributeName.length.signExtend()) if (attrKindId == 0) { throw Error("Unable to find '$attributeName' attribute kind id") } - return attrKindId + return LLVMAttributeKindId(attrKindId) } +data class LLVMAttributeKindId(val value: Int) + fun setFunctionNoUnwind(function: LLVMValueRef) { - val attribute = LLVMCreateEnumAttribute(LLVMGetTypeContext(function.type), nounwindAttrKindId, 0)!! - LLVMAddAttributeAtIndex(function, LLVMAttributeFunctionIndex, attribute) + addLlvmFunctionEnumAttribute(function, nounwindAttrKindId) } fun setFunctionNoReturn(function: LLVMValueRef) { - val attribute = LLVMCreateEnumAttribute(LLVMGetTypeContext(function.type), noreturnAttrKindId, 0)!! + addLlvmFunctionEnumAttribute(function, noreturnAttrKindId) +} + +fun setFunctionNoInline(function: LLVMValueRef) { + addLlvmFunctionEnumAttribute(function, noinlineAttrKindId) +} + +internal fun addLlvmFunctionEnumAttribute(function: LLVMValueRef, attrKindId: LLVMAttributeKindId, value: Long = 0) { + val attribute = createLlvmEnumAttribute(LLVMGetTypeContext(function.type)!!, attrKindId, value) + addLlvmFunctionAttribute(function, attribute) +} + +internal fun createLlvmEnumAttribute(llvmContext: LLVMContextRef, attrKindId: LLVMAttributeKindId, value: Long = 0) = + LLVMCreateEnumAttribute(llvmContext, attrKindId.value, value)!! + +internal fun addLlvmFunctionAttribute(function: LLVMValueRef, attribute: LLVMAttributeRef) { LLVMAddAttributeAtIndex(function, LLVMAttributeFunctionIndex, attribute) } fun addFunctionSignext(function: LLVMValueRef, index: Int, type: LLVMTypeRef?) { if (type == int1Type || type == int8Type || type == int16Type) { - val attribute = LLVMCreateEnumAttribute(LLVMGetTypeContext(function.type), signextAttrKindId, 0)!! + val attribute = createLlvmEnumAttribute(LLVMGetTypeContext(function.type)!!, signextAttrKindId) LLVMAddAttributeAtIndex(function, index, attribute) } } diff --git a/runtime/src/main/cpp/Exceptions.cpp b/runtime/src/main/cpp/Exceptions.cpp index 520b952d254..6a976b9bc10 100644 --- a/runtime/src/main/cpp/Exceptions.cpp +++ b/runtime/src/main/cpp/Exceptions.cpp @@ -121,12 +121,12 @@ extern "C" { // TODO: this implementation is just a hack, e.g. the result is inexact; // however it is better to have an inexact stacktrace than not to have any. -OBJ_GETTER0(GetCurrentStackTrace) { +NO_INLINE OBJ_GETTER0(Kotlin_getCurrentStackTrace) { #if OMIT_BACKTRACE return AllocArrayInstance(theNativePtrArrayTypeInfo, 0, OBJ_RESULT); #else - // Skips first 3 elements as irrelevant. - constexpr int kSkipFrames = 3; + // Skips first 2 elements as irrelevant: this function and primary Throwable constructor. + constexpr int kSkipFrames = 2; #if USE_GCC_UNWIND int depth = 0; _Unwind_Backtrace(depthCountCallback, &depth); diff --git a/runtime/src/main/cpp/Natives.cpp b/runtime/src/main/cpp/Natives.cpp index 7175df86651..edcbc1e2880 100644 --- a/runtime/src/main/cpp/Natives.cpp +++ b/runtime/src/main/cpp/Natives.cpp @@ -39,10 +39,6 @@ KInt Kotlin_Any_hashCode(KConstRef thiz) { return reinterpret_cast(thiz); } -OBJ_GETTER0(Kotlin_getCurrentStackTrace) { - RETURN_RESULT_OF0(GetCurrentStackTrace); -} - OBJ_GETTER(Kotlin_getStackTraceStrings, KConstRef stackTrace) { RETURN_RESULT_OF(GetStackTraceStrings, stackTrace); }