Track current exception (#4701)

This commit is contained in:
Alexander Shabalin
2021-02-21 11:35:03 +03:00
committed by Vasily Levchenko
parent a38e64a7c8
commit 3a5c6480a3
17 changed files with 319 additions and 64 deletions
@@ -461,7 +461,7 @@ private class ExportedElement(val kind: ElementKind,
"result", cfunction[0], Direction.KOTLIN_TO_C, builder)
builder.append(" return $result;\n")
}
builder.append(" } catch (ExceptionObjHolder& e) { TerminateWithUnhandledException(e.obj()); } \n")
builder.append(" } catch (ExceptionObjHolder& e) { TerminateWithUnhandledException(e.GetExceptionObject()); } \n")
builder.append("}\n")
@@ -905,7 +905,6 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|#define RUNTIME_NORETURN __attribute__((noreturn))
|
|extern "C" {
|void UpdateHeapRef(KObjHeader**, const KObjHeader*) RUNTIME_NOTHROW;
|void UpdateStackRef(KObjHeader**, const KObjHeader*) RUNTIME_NOTHROW;
|KObjHeader* AllocInstance(const KTypeInfo*, KObjHeader**) RUNTIME_NOTHROW;
|KObjHeader* DerefStablePointer(void*, KObjHeader**) RUNTIME_NOTHROW;
@@ -951,16 +950,10 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|};
|
|class ExceptionObjHolder {
| public:
| explicit ExceptionObjHolder(const KObjHeader* obj): obj_(nullptr) {
| ::UpdateHeapRef(&obj_, obj);
| }
| ~ExceptionObjHolder() {
| UpdateHeapRef(&obj_, nullptr);
| }
| KObjHeader* obj() { return obj_; }
| private:
| KObjHeader* obj_;
|public:
| virtual ~ExceptionObjHolder() = default;
|
| KObjHeader* GetExceptionObject() noexcept;
|};
|
|static void DisposeStablePointerImpl(${prefix}_KNativePtr ptr) {
@@ -862,14 +862,10 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
val beginCatch = context.llvm.cxaBeginCatchFunction
val exceptionRawPtr = call(beginCatch, listOf(exceptionRecord))
// Pointer to KotlinException instance:
val exceptionPtrPtr = bitcast(codegen.kObjHeaderPtrPtr, exceptionRawPtr, "")
// Pointer to Kotlin exception object:
// We do need a slot here, as otherwise exception instance could be freed by _cxa_end_catch.
val exceptionPtr = loadSlot(exceptionPtrPtr, true, "exception")
val exceptionPtr = call(context.llvm.Kotlin_getExceptionObject, listOf(exceptionRawPtr), Lifetime.GLOBAL)
// __cxa_end_catch performs some C++ cleanup, including calling `KotlinException` class destructor.
// __cxa_end_catch performs some C++ cleanup, including calling `ExceptionObjHolder` class destructor.
val endCatch = context.llvm.cxaEndCatchFunction
call(endCatch, listOf())
@@ -516,6 +516,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
val checkLifetimesConstraint = importRtFunction("CheckLifetimesConstraint")
val freezeSubgraph = importRtFunction("FreezeSubgraph")
val checkGlobalsAccessible = importRtFunction("CheckGlobalsAccessible")
val Kotlin_getExceptionObject = importRtFunction("Kotlin_getExceptionObject")
val kRefSharedHolderInitLocal = importRtFunction("KRefSharedHolder_initLocal")
val kRefSharedHolderInit = importRtFunction("KRefSharedHolder_init")
@@ -2545,6 +2545,16 @@ standaloneTest("exception_in_global_init") {
outputChecker = { s -> s.contains("Uncaught Kotlin exception: kotlin.IllegalStateException: FAIL") && !s.contains("in kotlin main") }
}
task rethrow_exception(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') // Uses exceptions.
source = "runtime/exceptions/rethrow.kt"
}
task throw_from_catch(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') // Uses exceptions.
source = "runtime/exceptions/throw_from_catch.kt"
}
standaloneTest("runtime_math_exceptions") {
enabled = (project.testTarget != 'wasm32')
source = "stdlib_external/numbers/MathExceptionTest.kt"
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2021 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 runtime.exceptions.rethtow
import kotlin.test.*
@Test
fun runTest() {
assertFailsWith<IllegalStateException>("My error") {
try {
error("My error")
} catch (e: Throwable) {
throw e
}
}
}
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2021 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 runtime.exceptions.throw_from_catch
import kotlin.test.*
@Test
fun runTest() {
assertFailsWith<IllegalStateException>("My another error") {
try {
error("My error")
} catch (e: Throwable) {
error("My another error")
}
}
}