[K/N] Make exception handling in initializers more consistent with jvm

^KT-57091
This commit is contained in:
Pavel Kunyavskiy
2023-03-03 17:54:48 +01:00
committed by Space Team
parent 0506d39d8a
commit dc2e072af2
29 changed files with 315 additions and 164 deletions
@@ -1557,34 +1557,6 @@ standaloneTest("initializers_workers2") {
useGoldenData = true
}
standaloneTest("initializers_failInInitializer1") {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
source = "codegen/initializers/failInInitializer1.kt"
useGoldenData = true
flags = ['-Xir-property-lazy-initialization=enable']
}
standaloneTest("initializers_failInInitializer2") {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
source = "codegen/initializers/failInInitializer2.kt"
useGoldenData = true
flags = ['-Xir-property-lazy-initialization=enable']
}
standaloneTest("initializers_failInInitializer3") {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
source = "codegen/initializers/failInInitializer3.kt"
useGoldenData = true
flags = ['-Xir-property-lazy-initialization=enable']
}
standaloneTest("initializers_failInInitializer4") {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
source = "codegen/initializers/failInInitializer4.kt"
useGoldenData = true
flags = ['-Xir-property-lazy-initialization=enable']
}
standaloneTest("initializers_when1") {
source = "codegen/initializers/when1.kt"
useGoldenData = true
@@ -2839,7 +2811,7 @@ standaloneTest("exception_in_global_init") {
enabled = (project.testTarget != 'wasm32') // Uses exceptions.
source = "runtime/exceptions/exception_in_global_init.kt"
expectedExitStatusChecker = { it != 0 }
outputChecker = { s -> s.contains("Uncaught Kotlin exception:") && s.coinains("FAIL") && !s.contains("in kotlin main") }
outputChecker = { s -> s.contains("Uncaught Kotlin exception:") && s.contains("FAIL") && !s.contains("in kotlin main") }
}
task rethrow_exception(type: KonanLocalTest) {
@@ -1,18 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
// FILE: lib.kt
val x: String = computeX()
fun computeX(): String = error("zzz")
// FILE: main.kt
fun main() {
try {
println(x)
} catch(t: IllegalStateException) {
println("caught")
}
}
@@ -1,28 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
// FILE: lib.kt
val x: String = computeX()
fun computeX(): String = error("zzz")
val y: String = computeY()
fun computeY(): String = "qzz"
// FILE: main.kt
@OptIn(ExperimentalStdlibApi::class)
fun main() {
try {
println(x)
} catch(t: IllegalStateException) {
println("caught")
}
try {
println(y)
} catch(t: kotlin.native.FileFailedToInitializeException) {
println("caught2")
}
}
@@ -1,2 +0,0 @@
caught
caught2
@@ -1,31 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
// FILE: lib.kt
import kotlin.native.concurrent.*
@ThreadLocal
val x: String = computeX()
fun computeX(): String = error("zzz")
val y: String = computeY()
fun computeY(): String = "qzz"
// FILE: main.kt
@OptIn(ExperimentalStdlibApi::class)
fun main() {
try {
println(x)
} catch(t: IllegalStateException) {
println("caught")
}
try {
println(y)
} catch(t: kotlin.native.FileFailedToInitializeException) {
println("caught2")
}
}
@@ -1,2 +0,0 @@
caught
caught2
@@ -1,32 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
// FILE: lib.kt
import kotlin.native.concurrent.*
@ThreadLocal
val x: String = computeX()
fun computeX(): String = error("zzz")
@ThreadLocal
val y: String = computeY()
fun computeY(): String = "qzz"
// FILE: main.kt
@OptIn(ExperimentalStdlibApi::class)
fun main() {
try {
println(x)
} catch(t: IllegalStateException) {
println("caught")
}
try {
println(y)
} catch(t: kotlin.native.FileFailedToInitializeException) {
println("caught2")
}
}
@@ -1,2 +0,0 @@
caught
caught2
@@ -44,7 +44,7 @@ void RUNTIME_NORETURN ThrowIllegalArgumentException();
void RUNTIME_NORETURN ThrowIllegalStateException();
void RUNTIME_NORETURN ThrowInvalidMutabilityException(KConstRef where);
void RUNTIME_NORETURN ThrowIncorrectDereferenceException();
void RUNTIME_NORETURN ThrowFileFailedToInitializeException();
void RUNTIME_NORETURN ThrowFileFailedToInitializeException(KRef reason);
void RUNTIME_NORETURN ThrowIllegalObjectSharingException(KConstNativePtr typeInfo, KConstNativePtr address);
void RUNTIME_NORETURN ThrowFreezingException(KRef toFreeze, KRef blocker);
// Prints out message of Throwable.
+13 -7
View File
@@ -464,14 +464,14 @@ static void CallInitGlobalAwaitInitialized(int *state) {
localState = atomicGetAcquire(state);
} while (localState != FILE_INITIALIZED && localState != FILE_FAILED_TO_INITIALIZE);
}
if (localState == FILE_FAILED_TO_INITIALIZE) ThrowFileFailedToInitializeException();
if (localState == FILE_FAILED_TO_INITIALIZE) ThrowFileFailedToInitializeException(nullptr);
}
NO_INLINE void CallInitGlobalPossiblyLock(int* state, void (*init)()) {
int localState = atomicGetAcquire(state);
if (localState == FILE_INITIALIZED) return;
if (localState == FILE_FAILED_TO_INITIALIZE)
ThrowFileFailedToInitializeException();
ThrowFileFailedToInitializeException(nullptr);
int threadId = konan::currentThreadId();
if ((localState & 3) == FILE_BEING_INITIALIZED) {
if ((localState & ~3) != (threadId << 2)) {
@@ -485,10 +485,13 @@ NO_INLINE void CallInitGlobalPossiblyLock(int* state, void (*init)()) {
init();
#else
try {
CurrentFrameGuard guard;
init();
} catch (...) {
} catch (ExceptionObjHolder& e) {
ObjHolder holder;
auto *exception = Kotlin_getExceptionObject(&e, holder.slot());
atomicSetRelease(state, FILE_FAILED_TO_INITIALIZE);
throw;
ThrowFileFailedToInitializeException(exception);
}
#endif
atomicSetRelease(state, FILE_INITIALIZED);
@@ -499,16 +502,19 @@ NO_INLINE void CallInitGlobalPossiblyLock(int* state, void (*init)()) {
void CallInitThreadLocal(int volatile* globalState, int* localState, void (*init)()) {
if (*localState == FILE_FAILED_TO_INITIALIZE || (globalState != nullptr && *globalState == FILE_FAILED_TO_INITIALIZE))
ThrowFileFailedToInitializeException();
ThrowFileFailedToInitializeException(nullptr);
*localState = FILE_INITIALIZED;
#if KONAN_NO_EXCEPTIONS
init();
#else
try {
CurrentFrameGuard guard;
init();
} catch(...) {
} catch(ExceptionObjHolder& e) {
ObjHolder holder;
auto *exception = Kotlin_getExceptionObject(&e, holder.slot());
*localState = FILE_FAILED_TO_INITIALIZE;
throw;
ThrowFileFailedToInitializeException(exception);
}
#endif
}
@@ -35,15 +35,6 @@ public class IncorrectDereferenceException : RuntimeException {
constructor(message: String) : super(message)
}
/**
* Exception thrown when there was an error during file initalization.
*/
@ExperimentalStdlibApi
public class FileFailedToInitializeException : RuntimeException {
constructor() : super()
constructor(message: String) : super(message)
}
/**
* Typealias describing custom exception reporting hook.
@@ -107,10 +107,20 @@ internal fun ThrowIncorrectDereferenceException() {
"Trying to access top level value not marked as @ThreadLocal or @SharedImmutable from non-main thread")
}
internal class FileFailedToInitializeException(message: String?, cause: Throwable?) : Error(message, cause)
@ExportForCppRuntime
@OptIn(ExperimentalStdlibApi::class)
internal fun ThrowFileFailedToInitializeException() {
throw FileFailedToInitializeException("There was an error during file initialization")
internal fun ThrowFileFailedToInitializeException(reason: Throwable?) {
if (reason is Error) {
throw reason
} else {
// https://youtrack.jetbrains.com/issue/KT-57134
// TODO: align exact exception hierarchy with jvm
// in jvm it's NoClassDefFound if reason is null, i.e. this is already failed class
// and ExceptionInInitializerError if it's non-null
throw FileFailedToInitializeException("There was an error during file or class initialization", reason)
}
}
internal class IrLinkageError(message: String?) : Error(message)