override fun visitLabel()

in jvm-agent/src/main/org/jetbrains/lincheck/jvm/agent/transformers/InlineMethodCallTransformer.kt [80:117]


    override fun visitLabel(label: Label) {
        if (!methodInfo.locals.hasInlines || looksLikeSuspendMethod || looksLikeBlocklistedMethod) {
            super.visitLabel(label)
            return
        }

        // It is not clear, could one label be used to mark the end of one inline call and
        // the start of another one. Nothing wrong instrument exists first.
        while (inlineStack.isNotEmpty()) {
            val (lvar, methodId, tryEndsCatchBeginsLabel, savedInlineDepth) = inlineStack.last()
            val cmp = methodInfo.labels.compare(lvar.endLabel, label)
            if (cmp > 0) break
            if (cmp < 0) {
                Logger.warn { "${className}.${methodName}: Inline call to ${lvar.inlineMethodName} should be finished at label ${lvar.endLabel} but still alive at ${label}." }
            }
            emitInlinedMethodEpilogue(methodId, tryEndsCatchBeginsLabel)
            inlineStack.removeLast()
            currentInlineDepth = savedInlineDepth
        }

        // Visit the label itself
        super.visitLabel(label)

        // Can one start label mark the beginning of several inlined methods?
        // One end label can mark several returns for sure.
        // Support multiple starts to be sure.
        // Sort starts by end labels (it provides proper nesting) and then variable slots (it provides stable sort)
        for (lvar in methodInfo.locals.inlinesStartAt(label)
            .filter { it.inlineMethodName != methodName && isSupportedInline(it) }
            .sortedWith(localVarInlineStartComparator)
        ) {
            // This cannot be inserted into `.filter` above because top-of-stack can change in this loop
            if (isNakedLambda(lvar)) continue
            inlineStack.add(
                emitInlineMethodPrologue(lvar)
            )
        }
    }