[K/N] Added function SetCurrentFrame to use in unwind block
This commit is contained in:
+1
@@ -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")
|
||||
|
||||
@@ -2561,6 +2561,17 @@ void leaveFrame(ObjHeader** start, int parameters, int count) {
|
||||
}
|
||||
}
|
||||
|
||||
template <bool Strict>
|
||||
void setCurrentFrame(ObjHeader** start) {
|
||||
MEMORY_LOG("SetCurrentFrame %p\n", start)
|
||||
FrameOverlay* frame = reinterpret_cast<FrameOverlay*>(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<false>(start, parameters, count);
|
||||
}
|
||||
|
||||
RUNTIME_NOTHROW void SetCurrentFrameStrict(ObjHeader** start) {
|
||||
setCurrentFrame<true>(start);
|
||||
}
|
||||
RUNTIME_NOTHROW void SetCurrentFrameRelaxed(ObjHeader** start) {
|
||||
setCurrentFrame<false>(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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -35,6 +35,7 @@ void EnsureDeclarationsEmitted() {
|
||||
ensureUsed(ZeroArrayRefs);
|
||||
ensureUsed(EnterFrame);
|
||||
ensureUsed(LeaveFrame);
|
||||
ensureUsed(SetCurrentFrame);
|
||||
ensureUsed(AddTLSRecord);
|
||||
ensureUsed(LookupTLS);
|
||||
ensureUsed(MutationCheck);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define RUNTIME_MEMORY_H
|
||||
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
|
||||
#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.
|
||||
|
||||
@@ -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<ObjHeader**>(currentFrame));
|
||||
ok = false;
|
||||
switch (exceptionHandling()) {
|
||||
case WorkerExceptionHandling::kIgnore:
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -35,3 +35,11 @@ void mm::ShadowStack::LeaveFrame(ObjHeader** start, int parameters, int count) n
|
||||
FrameOverlay* frame = reinterpret_cast<FrameOverlay*>(start);
|
||||
currentFrame_ = frame->previous;
|
||||
}
|
||||
|
||||
void mm::ShadowStack::SetCurrentFrame(ObjHeader** start) noexcept {
|
||||
currentFrame_ = reinterpret_cast<FrameOverlay*>(start);
|
||||
}
|
||||
|
||||
FrameOverlay* mm::ShadowStack::getCurrentFrame() noexcept {
|
||||
return currentFrame_;
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user