From cde51ecc3aab636008b79d25034e742e1556d2d9 Mon Sep 17 00:00:00 2001 From: Elena Lepilkina Date: Wed, 29 Sep 2021 17:49:02 +0300 Subject: [PATCH] [K/N] Added function SetCurrentFrame to use in unwind block --- .../kotlin/backend/konan/llvm/ContextUtils.kt | 1 + .../runtime/src/legacymm/cpp/Memory.cpp | 22 +++++++++ .../src/legacymm/cpp/MemoryPrivate.hpp | 1 + .../runtime/src/main/cpp/CompilerExport.cpp | 1 + kotlin-native/runtime/src/main/cpp/Memory.h | 6 +++ kotlin-native/runtime/src/main/cpp/Worker.cpp | 47 +++++++++++-------- .../runtime/src/mm/cpp/CallsChecker.cpp | 3 ++ kotlin-native/runtime/src/mm/cpp/Memory.cpp | 12 +++++ .../runtime/src/mm/cpp/ShadowStack.cpp | 8 ++++ .../runtime/src/mm/cpp/ShadowStack.hpp | 2 + .../runtime/src/relaxed/cpp/MemoryImpl.cpp | 4 ++ .../runtime/src/strict/cpp/MemoryImpl.cpp | 4 ++ 12 files changed, 91 insertions(+), 20 deletions(-) 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 75d1526684b..8a46477c411 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 @@ -456,6 +456,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti val zeroArrayRefsFunction = importRtFunction("ZeroArrayRefs") val enterFrameFunction = importRtFunction("EnterFrame") val leaveFrameFunction = importRtFunction("LeaveFrame") + val setCurrentFrameFunction = importRtFunction("SetCurrentFrame") val lookupInterfaceTableRecord = importRtFunction("LookupInterfaceTableRecord") val isInstanceFunction = importRtFunction("IsInstance") val isInstanceOfClassFastFunction = importRtFunction("IsInstanceOfClassFast") diff --git a/kotlin-native/runtime/src/legacymm/cpp/Memory.cpp b/kotlin-native/runtime/src/legacymm/cpp/Memory.cpp index 66e3f5ff5e3..8f28048837d 100644 --- a/kotlin-native/runtime/src/legacymm/cpp/Memory.cpp +++ b/kotlin-native/runtime/src/legacymm/cpp/Memory.cpp @@ -2561,6 +2561,17 @@ void leaveFrame(ObjHeader** start, int parameters, int count) { } } +template +void setCurrentFrame(ObjHeader** start) { + MEMORY_LOG("SetCurrentFrame %p\n", start) + FrameOverlay* frame = reinterpret_cast(start); + if (Strict) { + currentFrame = frame; + } else { + RuntimeFail("Relaxed memory model is deprecated and doesn't support exception handling proper way!\n"); + } +} + void suspendGC() { GC_LOG("suspendGC\n") memoryState->gcSuspendCount++; @@ -3466,6 +3477,13 @@ RUNTIME_NOTHROW void LeaveFrameRelaxed(ObjHeader** start, int parameters, int co leaveFrame(start, parameters, count); } +RUNTIME_NOTHROW void SetCurrentFrameStrict(ObjHeader** start) { + setCurrentFrame(start); +} +RUNTIME_NOTHROW void SetCurrentFrameRelaxed(ObjHeader** start) { + setCurrentFrame(start); +} + void Kotlin_native_internal_GC_collect(KRef) { #if USE_GC garbageCollect(); @@ -3654,6 +3672,10 @@ RUNTIME_NOTHROW void GC_RegisterWorker(void* worker) { #endif // USE_CYCLIC_GC } +RUNTIME_NOTHROW FrameOverlay* getCurrentFrame() { + return currentFrame; +} + RUNTIME_NOTHROW void GC_UnregisterWorker(void* worker) { #if USE_CYCLIC_GC cyclicRemoveWorker(worker, g_hasCyclicCollector); diff --git a/kotlin-native/runtime/src/legacymm/cpp/MemoryPrivate.hpp b/kotlin-native/runtime/src/legacymm/cpp/MemoryPrivate.hpp index cc2493d5568..8994afca150 100644 --- a/kotlin-native/runtime/src/legacymm/cpp/MemoryPrivate.hpp +++ b/kotlin-native/runtime/src/legacymm/cpp/MemoryPrivate.hpp @@ -326,6 +326,7 @@ MODEL_VARIANTS(void, UpdateHeapRefsInsideOneArray, const ArrayHeader* array, int int count); MODEL_VARIANTS(void, EnterFrame, ObjHeader** start, int parameters, int count); MODEL_VARIANTS(void, LeaveFrame, ObjHeader** start, int parameters, int count); +MODEL_VARIANTS(void, SetCurrentFrame, ObjHeader** start); void ReleaseHeapRef(const ObjHeader* object) RUNTIME_NOTHROW; MODEL_VARIANTS(void, ReleaseHeapRef, const ObjHeader* object); diff --git a/kotlin-native/runtime/src/main/cpp/CompilerExport.cpp b/kotlin-native/runtime/src/main/cpp/CompilerExport.cpp index 87d4a0dbc12..cb997680b26 100644 --- a/kotlin-native/runtime/src/main/cpp/CompilerExport.cpp +++ b/kotlin-native/runtime/src/main/cpp/CompilerExport.cpp @@ -35,6 +35,7 @@ void EnsureDeclarationsEmitted() { ensureUsed(ZeroArrayRefs); ensureUsed(EnterFrame); ensureUsed(LeaveFrame); + ensureUsed(SetCurrentFrame); ensureUsed(AddTLSRecord); ensureUsed(LookupTLS); ensureUsed(MutationCheck); diff --git a/kotlin-native/runtime/src/main/cpp/Memory.h b/kotlin-native/runtime/src/main/cpp/Memory.h index 4fb59df0d34..df91eb9a59d 100644 --- a/kotlin-native/runtime/src/main/cpp/Memory.h +++ b/kotlin-native/runtime/src/main/cpp/Memory.h @@ -18,6 +18,7 @@ #define RUNTIME_MEMORY_H #include +#include #include "KAssert.h" #include "Common.h" @@ -122,6 +123,7 @@ ALWAYS_INLINE inline bool isNullOrMarker(const ObjHeader* obj) noexcept { } class ForeignRefManager; +struct FrameOverlay; typedef ForeignRefManager* ForeignRefContext; #ifdef __cplusplus @@ -241,6 +243,10 @@ OBJ_GETTER(ReadHeapRefNoLock, ObjHeader* object, int32_t index); void EnterFrame(ObjHeader** start, int parameters, int count) RUNTIME_NOTHROW; // Called on frame leave, if it has object slots. void LeaveFrame(ObjHeader** start, int parameters, int count) RUNTIME_NOTHROW; +// Set current frame in case if exception caught. +void SetCurrentFrame(ObjHeader** start) RUNTIME_NOTHROW; +FrameOverlay* getCurrentFrame() RUNTIME_NOTHROW; + // Clears object subgraph references from memory subsystem, and optionally // checks if subgraph referenced by given root is disjoint from the rest of // object graph, i.e. no external references exists. diff --git a/kotlin-native/runtime/src/main/cpp/Worker.cpp b/kotlin-native/runtime/src/main/cpp/Worker.cpp index a54c879f32c..81f4f12d2f6 100644 --- a/kotlin-native/runtime/src/main/cpp/Worker.cpp +++ b/kotlin-native/runtime/src/main/cpp/Worker.cpp @@ -160,7 +160,7 @@ class Worker { bool waitForQueueLocked(KLong timeoutMicroseconds, KLong* remaining); - JobKind processQueueElement(bool blocking); + RUNTIME_NODEBUG JobKind processQueueElement(bool blocking); bool park(KLong timeoutMicroseconds, bool process); @@ -1052,21 +1052,22 @@ JobKind Worker::processQueueElement(bool blocking) { ObjHolder operationHolder, dummyHolder; KRef obj = DerefStablePointer(job.executeAfter.operation, operationHolder.slot()); try { -#if KONAN_OBJC_INTEROP - konan::AutoreleasePool autoreleasePool; -#endif - WorkerLaunchpad(obj, dummyHolder.slot()); - } catch (ExceptionObjHolder& e) { + #if KONAN_OBJC_INTEROP + konan::AutoreleasePool autoreleasePool; + #endif + WorkerLaunchpad(obj, dummyHolder.slot()); + } catch(ExceptionObjHolder& e) { switch (exceptionHandling()) { - case WorkerExceptionHandling::kIgnore: break; - case WorkerExceptionHandling::kDefault: - kotlin::ProcessUnhandledException(e.GetExceptionObject()); - break; - case WorkerExceptionHandling::kLog: - ReportUnhandledException(e.GetExceptionObject()); - break; + case WorkerExceptionHandling::kIgnore: break; + case WorkerExceptionHandling::kDefault: + kotlin::ProcessUnhandledException(e.GetExceptionObject()); + break; + case WorkerExceptionHandling::kLog: + ReportUnhandledException(e.GetExceptionObject()); + break; } } + DisposeStablePointer(job.executeAfter.operation); break; } @@ -1076,15 +1077,21 @@ JobKind Worker::processQueueElement(bool blocking) { ObjHolder argumentHolder; ObjHolder resultHolder; KRef argument = AdoptStablePointer(job.regularJob.argument, argumentHolder.slot()); + #if !KONAN_NO_EXCEPTIONS + FrameOverlay* currentFrame = getCurrentFrame(); + #else + RuntimeFail("Exceptions aren't supported!\n"); + #endif try { -#if KONAN_OBJC_INTEROP - konan::AutoreleasePool autoreleasePool; -#endif - job.regularJob.function(argument, resultHolder.slot()); - argumentHolder.clear(); - // Transfer the result. - result = transfer(&resultHolder, job.regularJob.transferMode); + #if KONAN_OBJC_INTEROP + konan::AutoreleasePool autoreleasePool; + #endif + job.regularJob.function(argument, resultHolder.slot()); + argumentHolder.clear(); + // Transfer the result. + result = transfer(&resultHolder, job.regularJob.transferMode); } catch (ExceptionObjHolder& e) { + SetCurrentFrame(reinterpret_cast(currentFrame)); ok = false; switch (exceptionHandling()) { case WorkerExceptionHandling::kIgnore: diff --git a/kotlin-native/runtime/src/mm/cpp/CallsChecker.cpp b/kotlin-native/runtime/src/mm/cpp/CallsChecker.cpp index 33995da3034..740de889ca5 100644 --- a/kotlin-native/runtime/src/mm/cpp/CallsChecker.cpp +++ b/kotlin-native/runtime/src/mm/cpp/CallsChecker.cpp @@ -51,6 +51,9 @@ extern "C" const char* Kotlin_callsCheckerGoodFunctionNames[] = { "_ZSt17rethrow_exceptionNSt15__exception_ptr13exception_ptrE", // std::rethrow_exception(std::__exception_ptr::exception_ptr) "_ZSt28_Rb_tree_rebalance_for_erasePSt18_Rb_tree_node_baseRS_", // std::_Rb_tree_rebalance_for_erase(std::_Rb_tree_node_base*, std::_Rb_tree_node_base&) "_ZN9__gnu_cxx27__verbose_terminate_handlerEv", // __gnu_cxx::__verbose_terminate_handler() + "_Znwm", // new + "_Znwy", + "_ZdlPv", // delete "__mingw_vsnprintf", "__cxa_allocate_exception", "__cxa_begin_catch", diff --git a/kotlin-native/runtime/src/mm/cpp/Memory.cpp b/kotlin-native/runtime/src/mm/cpp/Memory.cpp index 90029ce8cbe..4c6f2e54d93 100644 --- a/kotlin-native/runtime/src/mm/cpp/Memory.cpp +++ b/kotlin-native/runtime/src/mm/cpp/Memory.cpp @@ -238,6 +238,18 @@ extern "C" RUNTIME_NOTHROW void LeaveFrame(ObjHeader** start, int parameters, in threadData->shadowStack().LeaveFrame(start, parameters, count); } +extern "C" RUNTIME_NOTHROW void SetCurrentFrame(ObjHeader** start) { + auto* threadData = mm::ThreadRegistry::Instance().CurrentThreadData(); + AssertThreadState(threadData, ThreadState::kRunnable); + threadData->shadowStack().SetCurrentFrame(start); +} + +extern "C" RUNTIME_NOTHROW FrameOverlay* getCurrentFrame() { + auto* threadData = mm::ThreadRegistry::Instance().CurrentThreadData(); + AssertThreadState(threadData, ThreadState::kRunnable); + return threadData->shadowStack().getCurrentFrame(); +} + extern "C" RUNTIME_NOTHROW void AddTLSRecord(MemoryState* memory, void** key, int size) { memory->GetThreadData()->tls().AddRecord(key, size); } diff --git a/kotlin-native/runtime/src/mm/cpp/ShadowStack.cpp b/kotlin-native/runtime/src/mm/cpp/ShadowStack.cpp index 02bebb9cd4f..5fc76479efa 100644 --- a/kotlin-native/runtime/src/mm/cpp/ShadowStack.cpp +++ b/kotlin-native/runtime/src/mm/cpp/ShadowStack.cpp @@ -35,3 +35,11 @@ void mm::ShadowStack::LeaveFrame(ObjHeader** start, int parameters, int count) n FrameOverlay* frame = reinterpret_cast(start); currentFrame_ = frame->previous; } + +void mm::ShadowStack::SetCurrentFrame(ObjHeader** start) noexcept { + currentFrame_ = reinterpret_cast(start); +} + +FrameOverlay* mm::ShadowStack::getCurrentFrame() noexcept { + return currentFrame_; +} diff --git a/kotlin-native/runtime/src/mm/cpp/ShadowStack.hpp b/kotlin-native/runtime/src/mm/cpp/ShadowStack.hpp index 41f4901c89b..2f9980ed29f 100644 --- a/kotlin-native/runtime/src/mm/cpp/ShadowStack.hpp +++ b/kotlin-native/runtime/src/mm/cpp/ShadowStack.hpp @@ -53,6 +53,8 @@ public: void EnterFrame(ObjHeader** start, int parameters, int count) noexcept; void LeaveFrame(ObjHeader** start, int parameters, int count) noexcept; + void SetCurrentFrame(ObjHeader** start) noexcept; + FrameOverlay* getCurrentFrame() noexcept; Iterator begin() noexcept { return Iterator(currentFrame_); } Iterator end() noexcept { return Iterator(nullptr); } diff --git a/kotlin-native/runtime/src/relaxed/cpp/MemoryImpl.cpp b/kotlin-native/runtime/src/relaxed/cpp/MemoryImpl.cpp index 73e1678134a..bc93e2a8abb 100644 --- a/kotlin-native/runtime/src/relaxed/cpp/MemoryImpl.cpp +++ b/kotlin-native/runtime/src/relaxed/cpp/MemoryImpl.cpp @@ -63,6 +63,10 @@ RUNTIME_NOTHROW void LeaveFrame(ObjHeader** start, int parameters, int count) { LeaveFrameRelaxed(start, parameters, count); } +RUNTIME_NOTHROW void SetCurrentFrame(ObjHeader** start) { + SetCurrentFrameRelaxed(start); +} + RUNTIME_NOTHROW void UpdateStackRef(ObjHeader** location, const ObjHeader* object) { UpdateStackRefRelaxed(location, object); } diff --git a/kotlin-native/runtime/src/strict/cpp/MemoryImpl.cpp b/kotlin-native/runtime/src/strict/cpp/MemoryImpl.cpp index 7957e68cd8a..6610fd1dfe7 100644 --- a/kotlin-native/runtime/src/strict/cpp/MemoryImpl.cpp +++ b/kotlin-native/runtime/src/strict/cpp/MemoryImpl.cpp @@ -63,6 +63,10 @@ RUNTIME_NOTHROW void LeaveFrame(ObjHeader** start, int parameters, int count) { LeaveFrameStrict(start, parameters, count); } +RUNTIME_NOTHROW void SetCurrentFrame(ObjHeader** start) { + SetCurrentFrameStrict(start); +} + RUNTIME_NOTHROW void UpdateStackRef(ObjHeader** location, const ObjHeader* object) { UpdateStackRefStrict(location, object); }