in src/jvm/main/org/jetbrains/kotlinx/lincheck/strategy/managed/ManagedStrategy.kt [1824:1884]
override fun onMethodCallReturn(
threadDescriptor: ThreadDescriptor,
methodId: Int,
receiver: Any?,
params: Array<Any?>,
result: Any?,
interceptor: ResultInterceptor?,
): Unit = threadDescriptor.runInsideIgnoredSection {
val methodDescriptor = context.getMethodDescriptor(methodId)
// process intrinsic candidate methods
if (methodDescriptor.isIntrinsic) {
processIntrinsicMethodEffects(threadDescriptor, methodId, result)
}
val deterministicMethodDescriptor = interceptor?.getDeterministicMethodDescriptor()
if (deterministicMethodDescriptor != null) {
deterministicMethodDescriptor.processDeterministicMethodResult(receiver, params, result, interceptor)
}
val threadId = threadScheduler.getCurrentThreadId()
// check if the called method is an atomics API method
// (e.g., Atomic classes, AFU, VarHandle memory access API, etc.)
val atomicMethodDescriptor = getAtomicMethodDescriptor(receiver, methodDescriptor.methodName)
// get method's analysis section type
val methodSection = methodAnalysisSectionType(
receiver,
methodDescriptor.className,
methodDescriptor.methodName,
atomicMethodDescriptor,
deterministicMethodDescriptor,
)
if (collectTrace && methodSection != AnalysisSectionType.IGNORED) {
// an empty stack trace case is possible and can occur when we resume the coroutine,
// and it results in a call to a top-level actor `suspend` function;
// currently top-level actor functions are not represented in the `callStackTrace`,
// we should probably refactor and fix that, because it is very inconvenient
if (callStackTrace[threadId]!!.isNotEmpty()) {
val tracePoint = callStackTrace[threadId]!!.last().tracePoint
when {
result == Unit -> tracePoint.initializeVoidReturnedValue()
result == Injections.VOID_RESULT -> tracePoint.initializeVoidReturnedValue()
result == COROUTINE_SUSPENDED && isSuspendFunction(
methodDescriptor.className,
methodDescriptor.methodName,
params.asList()
) ->
tracePoint.initializeCoroutineSuspendedResult()
else -> tracePoint.initializeReturnedValue(
objectTracker.getObjectRepresentation(result),
objectFqTypeName(result)
)
}
afterMethodCall(threadId, tracePoint)
traceCollector?.addStateRepresentation()
}
}
// if the method has certain guarantees, leave the corresponding section
leaveAnalysisSection(threadId, methodSection)
}