[K/N] Replaced safe points to prologue

This commit is contained in:
Elena Lepilkina
2021-10-27 18:43:51 +03:00
committed by Space
parent 15dcfa2837
commit f67941e244
11 changed files with 38 additions and 58 deletions
@@ -434,7 +434,7 @@ internal abstract class FunctionGenerationContext(
val codegen: CodeGenerator,
private val startLocation: LocationInfo?,
private val endLocation: LocationInfo?,
private val switchToRunnable: Boolean,
switchToRunnable: Boolean,
internal val irFunction: IrFunction? = null
) : ContextUtils {
@@ -480,10 +480,13 @@ internal abstract class FunctionGenerationContext(
protected open val needCleanupLandingpadAndLeaveFrame: Boolean
get() = irFunction?.annotations?.hasAnnotation(RuntimeNames.exportForCppRuntime) == true || // Exported to foreign code
(!stackLocalsManager.isEmpty() && context.memoryModel != MemoryModel.EXPERIMENTAL) ||
(context.memoryModel == MemoryModel.EXPERIMENTAL && switchToRunnable)
switchToRunnable
private var setCurrentFrameIsCalled: Boolean = false
private val switchToRunnable: Boolean =
context.memoryModel == MemoryModel.EXPERIMENTAL && switchToRunnable
val stackLocalsManager = StackLocalsManagerImpl(this, stackLocalsInitBb)
data class FunctionInvokeInformation(
@@ -910,11 +913,6 @@ internal abstract class FunctionGenerationContext(
}
call(context.llvm.setCurrentFrameFunction, listOf(slotsPhi!!))
setCurrentFrameIsCalled = true
if (context.memoryModel == MemoryModel.EXPERIMENTAL) {
if (!forbidRuntime) {
call(context.llvm.Kotlin_mm_safePointExceptionUnwind, emptyList())
}
}
return landingpad
}
@@ -1502,7 +1500,7 @@ internal abstract class FunctionGenerationContext(
}
releaseVars()
handleEpilogueForExperimentalMM(context.llvm.Kotlin_mm_safePointExceptionUnwind)
handleEpilogueExperimentalMM()
LLVMBuildResume(builder, landingpad)
}
}
@@ -1514,14 +1512,11 @@ internal abstract class FunctionGenerationContext(
* places with inconsistent stack layout. So we setup debug info only for this part of bb.
*/
startLocation?.let { debugLocation(it, it) }
val needStateSwitch = context.memoryModel == MemoryModel.EXPERIMENTAL && switchToRunnable
if (needsRuntimeInit || needStateSwitch) {
if (needsRuntimeInit || switchToRunnable) {
check(!forbidRuntime) { "Attempt to init runtime where runtime usage is forbidden" }
call(context.llvm.initRuntimeIfNeeded, emptyList())
}
if (needStateSwitch) {
switchThreadState(Runnable)
}
handlePrologueExperimentalMM()
if (needSlots || needCleanupLandingpadAndLeaveFrame) {
call(context.llvm.enterFrameFunction, listOf(slotsPhi!!, Int32(vars.skipSlots).llvm, Int32(slotCount).llvm))
} else {
@@ -1577,18 +1572,22 @@ internal abstract class FunctionGenerationContext(
protected fun onReturn() {
releaseVars()
handleEpilogueForExperimentalMM(context.llvm.Kotlin_mm_safePointFunctionEpilogue)
handleEpilogueExperimentalMM()
}
private fun handleEpilogueForExperimentalMM(safePointFunction: LlvmCallable) {
if (context.memoryModel == MemoryModel.EXPERIMENTAL) {
if (!forbidRuntime) {
call(safePointFunction, emptyList())
}
if (switchToRunnable) {
check(!forbidRuntime) { "Generating a bridge when runtime is forbidden" }
switchThreadState(Native)
}
private fun handlePrologueExperimentalMM() {
if (switchToRunnable) {
switchThreadState(Runnable)
}
if (context.memoryModel == MemoryModel.EXPERIMENTAL && !forbidRuntime) {
call(context.llvm.Kotlin_mm_safePointFunctionPrologue, emptyList())
}
}
private fun handleEpilogueExperimentalMM() {
if (switchToRunnable) {
check(!forbidRuntime) { "Generating a bridge when runtime is forbidden" }
switchThreadState(Native)
}
}
@@ -507,9 +507,8 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti
private val Kotlin_ObjCExport_NSIntegerTypeProvider by lazyRtFunction
private val Kotlin_longTypeProvider by lazyRtFunction
val Kotlin_mm_safePointFunctionEpilogue by lazyRtFunction
val Kotlin_mm_safePointFunctionPrologue by lazyRtFunction
val Kotlin_mm_safePointWhileLoopBody by lazyRtFunction
val Kotlin_mm_safePointExceptionUnwind by lazyRtFunction
val tlsMode by lazy {
when (target) {
@@ -67,9 +67,8 @@ public:
class GCSchedulerThreadData {
public:
static constexpr size_t kFunctionEpilogueWeight = 1;
static constexpr size_t kFunctionPrologueWeight = 1;
static constexpr size_t kLoopBodyWeight = 1;
static constexpr size_t kExceptionUnwindWeight = 1;
explicit GCSchedulerThreadData(GCSchedulerConfig& config, std::function<void(GCSchedulerThreadData&)> onSafePoint) noexcept :
config_(config), onSafePoint_(std::move(onSafePoint)) {
@@ -33,9 +33,8 @@ public:
explicit ThreadData(NoOpGC& gc, mm::ThreadData& threadData) noexcept {}
~ThreadData() = default;
void SafePointFunctionEpilogue() noexcept {}
void SafePointFunctionPrologue() noexcept {}
void SafePointLoopBody() noexcept {}
void SafePointExceptionUnwind() noexcept {}
void SafePointAllocation(size_t size) noexcept {}
void PerformFullGC() noexcept {}
@@ -64,18 +64,14 @@ std::atomic<gc::SameThreadMarkAndSweep::SafepointFlag> gSafepointFlag = gc::Same
} // namespace
ALWAYS_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointFunctionEpilogue() noexcept {
SafePointRegular(GCSchedulerThreadData::kFunctionEpilogueWeight);
ALWAYS_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointFunctionPrologue() noexcept {
SafePointRegular(GCSchedulerThreadData::kFunctionPrologueWeight);
}
ALWAYS_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointLoopBody() noexcept {
SafePointRegular(GCSchedulerThreadData::kLoopBodyWeight);
}
ALWAYS_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointExceptionUnwind() noexcept {
SafePointRegular(GCSchedulerThreadData::kExceptionUnwindWeight);
}
void gc::SameThreadMarkAndSweep::ThreadData::SafePointAllocation(size_t size) noexcept {
threadData_.gcScheduler().OnSafePointAllocation(size);
SafepointFlag flag = gSafepointFlag.load();
@@ -52,7 +52,7 @@ public:
explicit ThreadData(SameThreadMarkAndSweep& gc, mm::ThreadData& threadData) noexcept : gc_(gc), threadData_(threadData) {}
~ThreadData() = default;
void SafePointFunctionEpilogue() noexcept;
void SafePointFunctionPrologue() noexcept;
void SafePointLoopBody() noexcept;
void SafePointExceptionUnwind() noexcept;
void SafePointAllocation(size_t size) noexcept;
@@ -785,7 +785,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsCollect) {
for (int i = 1; i < kDefaultThreadCount; ++i) {
gcFutures[i] =
mutators[i].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().SafePointFunctionEpilogue(); });
mutators[i].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().SafePointFunctionPrologue(); });
}
for (auto& future : gcFutures) {
@@ -906,7 +906,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRe
for (int i = 1; i < kDefaultThreadCount; ++i) {
gcFutures[i] = mutators[i].Execute([i, expandRootSet](mm::ThreadData& threadData, Mutator& mutator) {
expandRootSet(threadData, mutator, i);
threadData.gc().SafePointFunctionEpilogue();
threadData.gc().SafePointFunctionPrologue();
});
}
@@ -970,7 +970,7 @@ TEST_F(SameThreadMarkAndSweepTest, CrossThreadReference) {
for (int i = 1; i < kDefaultThreadCount; ++i) {
gcFutures[i] =
mutators[i].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().SafePointFunctionEpilogue(); });
mutators[i].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().SafePointFunctionPrologue(); });
}
for (auto& future : gcFutures) {
@@ -1034,7 +1034,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsWeaks) {
for (int i = 1; i < kDefaultThreadCount; ++i) {
gcFutures[i] = mutators[i].Execute([weak](mm::ThreadData& threadData, Mutator& mutator) {
threadData.gc().SafePointFunctionEpilogue();
threadData.gc().SafePointFunctionPrologue();
EXPECT_THAT((*weak)->referred, nullptr);
});
}
@@ -1092,7 +1092,7 @@ TEST_F(SameThreadMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
// All the other threads are stopping at safe points.
for (int i = 1; i < kDefaultThreadCount; ++i) {
gcFutures[i] =
mutators[i].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().SafePointFunctionEpilogue(); });
mutators[i].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().SafePointFunctionPrologue(); });
}
// GC will be completed first
@@ -3733,7 +3733,7 @@ ALWAYS_INLINE RUNTIME_NOTHROW void Kotlin_mm_switchThreadStateRunnable() {
// no-op, used by the new MM only.
}
ALWAYS_INLINE RUNTIME_NOTHROW void Kotlin_mm_safePointFunctionEpilogue() {
ALWAYS_INLINE RUNTIME_NOTHROW void Kotlin_mm_safePointFunctionPrologue() {
// no-op, used by the new MM only.
}
@@ -3741,10 +3741,6 @@ ALWAYS_INLINE RUNTIME_NOTHROW void Kotlin_mm_safePointWhileLoopBody() {
// no-op, used by the new MM only.
}
ALWAYS_INLINE RUNTIME_NOTHROW void Kotlin_mm_safePointExceptionUnwind() {
// no-op, used by the new MM only.
}
} // extern "C"
#if !KONAN_NO_EXCEPTIONS
@@ -46,7 +46,6 @@ void EnsureDeclarationsEmitted() {
ensureUsed(CheckGlobalsAccessible);
ensureUsed(Kotlin_mm_switchThreadStateNative);
ensureUsed(Kotlin_mm_switchThreadStateRunnable);
ensureUsed(Kotlin_mm_safePointFunctionEpilogue);
ensureUsed(Kotlin_mm_safePointFunctionPrologue);
ensureUsed(Kotlin_mm_safePointWhileLoopBody);
ensureUsed(Kotlin_mm_safePointExceptionUnwind);
}
+1 -2
View File
@@ -332,9 +332,8 @@ ALWAYS_INLINE RUNTIME_NOTHROW void Kotlin_mm_switchThreadStateNative();
ALWAYS_INLINE RUNTIME_NOTHROW void Kotlin_mm_switchThreadStateRunnable();
// Safe point callbacks from Kotlin code generator.
void Kotlin_mm_safePointFunctionEpilogue() RUNTIME_NOTHROW;
void Kotlin_mm_safePointFunctionPrologue() RUNTIME_NOTHROW;
void Kotlin_mm_safePointWhileLoopBody() RUNTIME_NOTHROW;
void Kotlin_mm_safePointExceptionUnwind() RUNTIME_NOTHROW;
#ifdef __cplusplus
}
+2 -8
View File
@@ -533,10 +533,10 @@ extern "C" void CheckGlobalsAccessible() {
// Always accessible
}
extern "C" RUNTIME_NOTHROW ALWAYS_INLINE void Kotlin_mm_safePointFunctionEpilogue() {
extern "C" RUNTIME_NOTHROW ALWAYS_INLINE void Kotlin_mm_safePointFunctionPrologue() {
auto* threadData = mm::ThreadRegistry::Instance().CurrentThreadData();
AssertThreadState(threadData, ThreadState::kRunnable);
threadData->gc().SafePointFunctionEpilogue();
threadData->gc().SafePointFunctionPrologue();
}
extern "C" RUNTIME_NOTHROW ALWAYS_INLINE void Kotlin_mm_safePointWhileLoopBody() {
@@ -545,12 +545,6 @@ extern "C" RUNTIME_NOTHROW ALWAYS_INLINE void Kotlin_mm_safePointWhileLoopBody()
threadData->gc().SafePointLoopBody();
}
extern "C" RUNTIME_NOTHROW ALWAYS_INLINE void Kotlin_mm_safePointExceptionUnwind() {
auto* threadData = mm::ThreadRegistry::Instance().CurrentThreadData();
AssertThreadState(threadData, ThreadState::kRunnable);
threadData->gc().SafePointExceptionUnwind();
}
extern "C" ALWAYS_INLINE RUNTIME_NOTHROW void Kotlin_mm_switchThreadStateNative() {
SwitchThreadState(mm::ThreadRegistry::Instance().CurrentThreadData(), ThreadState::kNative);
}