Skip to content

Commit c52c0e2

Browse files
author
Michael Bogdanov
committed
Write proper start label for inlined constructor parameters (start label was shifted by additional captured parameters injection)
1 parent 0cf1c8d commit c52c0e2

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ private void generateConstructorAndFields(
285285
"<init>", constructorDescriptor,
286286
null, ArrayUtil.EMPTY_STRING_ARRAY);
287287

288+
final Label newBodyStartLabel = new Label();
289+
constructorVisitor.visitLabel(newBodyStartLabel);
288290
//initialize captured fields
289291
List<NewJavaField> newFieldsWithSkipped = TransformationUtilsKt.getNewFieldsToGenerate(allCapturedBuilder.listCaptured());
290292
List<FieldInfo> fieldInfoWithSkipped = TransformationUtilsKt.transformToFieldInfo(
@@ -318,7 +320,20 @@ private void generateConstructorAndFields(
318320
}
319321
}
320322

321-
inlineMethodAndUpdateGlobalResult(parentRemapper, capturedFieldInitializer, constructor, constructorInlineBuilder, true);
323+
MethodNode intermediateMethodNode = new MethodNode(AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "<init>", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY);
324+
inlineMethodAndUpdateGlobalResult(parentRemapper, intermediateMethodNode, constructor, constructorInlineBuilder, true);
325+
326+
AbstractInsnNode first = intermediateMethodNode.instructions.getFirst();
327+
final Label oldStartLabel = first instanceof LabelNode ? ((LabelNode) first).getLabel() : null;
328+
intermediateMethodNode.accept(new MethodBodyVisitor(capturedFieldInitializer) {
329+
@Override
330+
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
331+
if (oldStartLabel == start) {
332+
start = newBodyStartLabel;//patch for jack&jill
333+
}
334+
super.visitLocalVariable(name, desc, signature, start, end, index);
335+
}
336+
});
322337
constructorVisitor.visitEnd();
323338
AsmUtil.genClosureFields(TransformationUtilsKt.toNameTypePair(TransformationUtilsKt.filterSkipped(newFieldsWithSkipped)), classBuilder);
324339
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
public inline fun <T> Iterable(crossinline iterator: () -> Iterator<T>): Iterable<T> = object : Iterable<T> {
2+
override fun iterator(): Iterator<T> = iterator()
3+
}
4+
5+
public fun IntArray.asIterable(): Iterable<Int> {
6+
return Iterable { this.iterator() }
7+
}
8+
/*Threre are two constuctors so we should be sure that we check required one by checking 'receiver$0$inlined' assign*/
9+
// 1 <init>\(\[I\)V\s+L0\s+ALOAD 0\s+ALOAD 1\s+PUTFIELD InlinedConstuctorKt\$asIterable\$\$inlined\$Iterable\$1\.receiver\$0\$inlined : \[I
10+
// 1 LOCALVARIABLE this LInlinedConstuctorKt\$asIterable\$\$inlined\$Iterable\$1; L0 L2 0
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
open class A(val z: String) {
2+
3+
}
4+
5+
inline fun test(crossinline s: () -> String) {
6+
object : A("123") {
7+
val x = s();
8+
}
9+
}
10+
11+
fun main(args: Array<String>) {
12+
var z = "123";
13+
test { z }
14+
}
15+
16+
/*Threre are two constuctors so we should be sure that we check LOCALVARIABLEs from same method*/
17+
// 1 LOCALVARIABLE this LInlinedConstuctorWithSuperCallParamsKt\$main\$\$inlined\$test\$1; L0 L7 0\s+LOCALVARIABLE \$super_call_param\$1 Ljava/lang/String; L0 L7 1

0 commit comments

Comments
 (0)