From: Mikhail Bogdanov <mikhael.bogdanov@jetbrains.com>
Date: Sat, 5 Sep 2020 21:26:10 +0200
Subject: compiler/backend: Backport fix for compiling with ASM 8
Origin: https://github.com/JetBrains/kotlin/commit/db50afeafee3442069cf477f85f7195dbd228dcc
Bug: https://youtrack.jetbrains.com/issue/KT-39013
Forwarded: not-needed
Last-Update: 2021-04-22

General rule to use linkedLabel or linkWithLabel when label from node is reused
in other instructions. If label is not linked then it will point to another
labelNode when visited
---
 .../jetbrains/kotlin/codegen/ExpressionCodegen.java  |  2 +-
 .../src/org/jetbrains/kotlin/codegen/codegenUtil.kt  | 20 ++++++++++++++++++++
 .../coroutines/CoroutineTransformerMethodVisitor.kt  |  3 ++-
 .../codegen/inline/InlineCodegenForDefaultBody.kt    |  4 +++-
 .../codegen/inline/InternalFinallyBlockInliner.java  |  3 ++-
 .../jetbrains/kotlin/codegen/inline/MethodInliner.kt |  2 +-
 .../nullCheck/RedundantNullCheckMethodTransformer.kt |  5 +++--
 .../kotlin/backend/jvm/codegen/ExpressionCodegen.kt  |  4 +++-
 8 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java
index 61b42d4..c7cc6f6 100644
--- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java
+++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java
@@ -1535,7 +1535,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
             assert topOfStack == finallyBlockStackElement : "Top element of stack doesn't equals processing finally block";
 
             KtTryExpression jetTryExpression = finallyBlockStackElement.expression;
-            Label finallyStart = new Label();
+            Label finallyStart = linkedLabel();
             v.mark(finallyStart);
             finallyBlockStackElement.addGapLabel(finallyStart);
             if (isFinallyMarkerRequired(context)) {
diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt
index 2127ada..46a2d1b 100644
--- a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt
+++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt
@@ -58,6 +58,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes.*
 import org.jetbrains.org.objectweb.asm.Type
 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
 import org.jetbrains.org.objectweb.asm.commons.Method
+import org.jetbrains.org.objectweb.asm.tree.LabelNode
 import org.jetbrains.org.objectweb.asm.tree.MethodNode
 import org.jetbrains.org.objectweb.asm.util.Textifier
 import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor
@@ -660,3 +661,22 @@ private fun generateLambdaForRunSuspend(
     lambdaBuilder.done()
     return lambdaBuilder.thisName
 }
+
+internal fun LabelNode.linkWithLabel(): LabelNode {
+    // Remember labelNode in label and vise versa.
+    // Before ASM 8 there was JB patch in MethodNode that makes such linking in constructor of LabelNode.
+    //
+    // protected LabelNode getLabelNode(final Label label) {
+    //    if (!(label.info instanceof LabelNode)) {
+    //      //label.info = new LabelNode(label); //[JB: needed for Coverage agent]
+    //      label.info = new LabelNode(); //ASM 8
+    //    }
+    //    return (LabelNode) label.info;
+    //  }
+    if (label.info == null) {
+        label.info = this
+    }
+    return this
+}
+
+fun linkedLabel(): Label = LabelNode().linkWithLabel().label
diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt
index 7946b75..a7a3420 100644
--- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt
+++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.codegen.optimization.common.*
 import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer
 import org.jetbrains.kotlin.codegen.optimization.fixStack.top
 import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
+import org.jetbrains.kotlin.codegen.linkWithLabel
 import org.jetbrains.kotlin.config.LanguageVersionSettings
 import org.jetbrains.kotlin.config.isReleaseCoroutines
 import org.jetbrains.kotlin.diagnostics.DiagnosticSink
@@ -666,7 +667,7 @@ class CoroutineTransformerMethodVisitor(
         methodNode: MethodNode,
         suspendMarkerVarIndex: Int
     ): LabelNode {
-        val continuationLabel = LabelNode()
+        val continuationLabel = LabelNode().linkWithLabel()
         val continuationLabelAfterLoadedResult = LabelNode()
         val suspendElementLineNumber = lineNumber
         var nextLineNumberNode = suspension.suspensionCallEnd.findNextOrNull { it is LineNumberNode } as? LineNumberNode
diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt
index be30fb3..5d3a3b2 100644
--- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt
+++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt
@@ -6,6 +6,7 @@
 package org.jetbrains.kotlin.codegen.inline
 
 import org.jetbrains.kotlin.codegen.*
+import org.jetbrains.kotlin.codegen.linkWithLabel
 import org.jetbrains.kotlin.codegen.state.GenerationState
 import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
 import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -16,6 +17,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
 import org.jetbrains.org.objectweb.asm.Label
 import org.jetbrains.org.objectweb.asm.Type
+import org.jetbrains.org.objectweb.asm.tree.LabelNode
 import org.jetbrains.org.objectweb.asm.tree.MethodNode
 
 class InlineCodegenForDefaultBody(
@@ -41,7 +43,7 @@ class InlineCodegenForDefaultBody(
 
     private val jvmSignature: JvmMethodGenericSignature
 
-    private val methodStartLabel = Label()
+    private val methodStartLabel = linkedLabel()
 
     init {
         assert(InlineUtil.isInline(function)) {
diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java
index f309c00..b16c231 100644
--- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java
+++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java
@@ -33,6 +33,7 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.*;
 
+import static org.jetbrains.kotlin.codegen.CodegenUtilKt.linkedLabel;
 import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.*;
 import static org.jetbrains.kotlin.codegen.inline.MethodInlinerUtilKt.getNextMeaningful;
 
@@ -187,7 +188,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
                 //Creating temp node for finally block copy with some additional instruction
                 MethodNode finallyBlockCopy = createEmptyMethodNode();
                 Label newFinallyStart = new Label();
-                Label insertedBlockEnd = new Label();
+                Label insertedBlockEnd = linkedLabel();
 
                 boolean generateAloadAstore = nonLocalReturnType != Type.VOID_TYPE && !finallyInfo.isEmpty();
                 if (generateAloadAstore) {
diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt
index 364c266..d83ec58 100644
--- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt
+++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt
@@ -92,7 +92,7 @@ class MethodInliner(
         }
 
         //substitute returns with "goto end" instruction to keep non local returns in lambdas
-        val end = Label()
+        val end = linkedLabel()
         val isTransformingAnonymousObject = nodeRemapper is RegeneratedLambdaFieldRemapper
         transformedNode = doInline(transformedNode)
         if (!isTransformingAnonymousObject) {
diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/nullCheck/RedundantNullCheckMethodTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/nullCheck/RedundantNullCheckMethodTransformer.kt
index 5ecfe35..3ffff6e 100644
--- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/nullCheck/RedundantNullCheckMethodTransformer.kt
+++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/nullCheck/RedundantNullCheckMethodTransformer.kt
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.optimization.nullCheck
 import org.jetbrains.kotlin.codegen.coroutines.withInstructionAdapter
 import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
 import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
+import org.jetbrains.kotlin.codegen.linkWithLabel
 import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
 import org.jetbrains.kotlin.codegen.optimization.common.debugText
 import org.jetbrains.kotlin.codegen.optimization.common.isInsn
@@ -246,7 +247,7 @@ class RedundantNullCheckMethodTransformer(private val generationState: Generatio
                 //  <...>   -- v is null here
 
                 val jumpsIfNull = insn.opcode == Opcodes.IFNULL
-                val originalLabel = insn.label
+                val originalLabel = insn.label.linkWithLabel()
                 originalLabels[insn] = originalLabel
                 insn.label = synthetic(LabelNode(Label()))
 
@@ -310,7 +311,7 @@ class RedundantNullCheckMethodTransformer(private val generationState: Generatio
                 val originalLabel: LabelNode?
                 val insertAfterNotNull: AbstractInsnNode
                 if (jumpsIfInstance) {
-                    originalLabel = next.label
+                    originalLabel = next.label.linkWithLabel()
                     originalLabels[next] = next.label
                     val newLabel = synthetic(LabelNode(Label()))
                     methodNode.instructions.add(newLabel)
diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt
index 5aff0a6..9b1e28e 100644
--- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt
+++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt
@@ -1087,7 +1087,7 @@ class ExpressionCodegen(
             assert(topOfStack === tryInfo) { "Top element of stack doesn't equals processing finally block" }
 
             val tryBlock = tryInfo.tryBlock
-            val finallyStart = markNewLabel()
+            val finallyStart = markNewLinkedLabel()
             tryInfo.gaps.add(finallyStart)
 
             //noinspection ConstantConditions
@@ -1335,6 +1335,8 @@ class ExpressionCodegen(
 
     private fun markNewLabel() = Label().apply { mv.visitLabel(this) }
 
+    private fun markNewLinkedLabel() = linkedLabel().apply { mv.visitLabel(this) }
+
     private fun IrElement.markLineNumber(startOffset: Boolean) {
         val offset = if (startOffset) this.startOffset else endOffset
         if (offset < 0) {
