Fix for KT-16532: Kotlin 1.1 RC - Android cross-inline synchronized won't run

Finnaly markers are used only for non-local return processing and are removed after inlining  to non-inline functions, same deletion should be performed on inlining to anonymous objects

 #KT-16532 Fixed
This commit is contained in:
Mikhael Bogdanov
2017-02-28 11:58:29 +01:00
parent 387c91f957
commit 21de67cac1
5 changed files with 56 additions and 23 deletions
@@ -141,12 +141,12 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
List<CapturedParamInfo> additionalFakeParams =
extractParametersMappingAndPatchConstructor(constructor, allCapturedParamBuilder, constructorParamBuilder,
transformationInfo, parentRemapper);
List<MethodVisitor> deferringMethods = new ArrayList<MethodVisitor>();
List<DeferredMethodVisitor> deferringMethods = new ArrayList<DeferredMethodVisitor>();
generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, parentRemapper, additionalFakeParams);
for (MethodNode next : methodsToTransform) {
MethodVisitor deferringVisitor = newMethod(classBuilder, next);
DeferredMethodVisitor deferringVisitor = newMethod(classBuilder, next);
InlineResult funResult =
inlineMethodAndUpdateGlobalResult(parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false);
@@ -161,7 +161,8 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
deferringMethods.add(deferringVisitor);
}
for (MethodVisitor method : deferringMethods) {
for (DeferredMethodVisitor method : deferringMethods) {
InlineCodegenUtil.removeFinallyMarkers(method.getIntermediate());
method.visitEnd();
}
@@ -313,6 +314,7 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
MethodNode intermediateMethodNode =
new MethodNode(AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "<init>", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY);
inlineMethodAndUpdateGlobalResult(parentRemapper, intermediateMethodNode, constructor, constructorInlineBuilder, true);
InlineCodegenUtil.removeFinallyMarkers(intermediateMethodNode);
AbstractInsnNode first = intermediateMethodNode.instructions.getFirst();
final Label oldStartLabel = first instanceof LabelNode ? ((LabelNode) first).getLabel() : null;
@@ -466,7 +466,9 @@ public class InlineCodegen extends CallGenerator {
adapter, infos, ((StackValue.Local) remapper.remap(parameters.getArgsSizeOnStack() + 1).value).index
);
removeStaticInitializationTrigger(adapter);
removeFinallyMarkers(adapter);
if (!InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) {
InlineCodegenUtil.removeFinallyMarkers(adapter);
}
adapter.accept(new MethodBodyVisitor(codegen.v));
@@ -1024,25 +1026,6 @@ public class InlineCodegen extends CallGenerator {
//processor.substituteLocalVarTable(intoNode);
}
private void removeFinallyMarkers(@NotNull MethodNode intoNode) {
if (InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) return;
InsnList instructions = intoNode.instructions;
AbstractInsnNode curInstr = instructions.getFirst();
while (curInstr != null) {
if (InlineCodegenUtil.isFinallyMarker(curInstr)) {
AbstractInsnNode marker = curInstr;
//just to assert
getConstant(marker.getPrevious());
curInstr = curInstr.getNext();
instructions.remove(marker.getPrevious());
instructions.remove(marker);
continue;
}
curInstr = curInstr.getNext();
}
}
@NotNull
public static SourceMapper createNestedSourceMapper(@NotNull SMAPAndMethodNode nodeAndSmap, @NotNull SourceMapper parent) {
return new NestedSourceMapper(parent, nodeAndSmap.getSortedRanges(), nodeAndSmap.getClassSMAP().getSourceInfo());
@@ -466,6 +466,23 @@ public class InlineCodegenUtil {
}
}
public static void removeFinallyMarkers(@NotNull MethodNode intoNode) {
InsnList instructions = intoNode.instructions;
AbstractInsnNode curInstr = instructions.getFirst();
while (curInstr != null) {
if (isFinallyMarker(curInstr)) {
AbstractInsnNode marker = curInstr;
//just to assert
getConstant(marker.getPrevious());
curInstr = curInstr.getNext();
instructions.remove(marker.getPrevious());
instructions.remove(marker);
continue;
}
curInstr = curInstr.getNext();
}
}
public static void addInlineMarker(@NotNull InstructionAdapter v, boolean isStartNotEnd) {
v.visitMethodInsn(
Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME,
@@ -0,0 +1,25 @@
inline fun test(crossinline l: () -> String) {
{
l()
}()
object {
val z = l() //constuctor
}
}
fun box(): String {
var z = "fail"
test {
synchronized("123") {
z = "OK"
z
}
}
return z
}
// 0 finallyStart
// 0 finallyEnd
@@ -1247,6 +1247,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/inline"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("finallyMarkers.kt")
public void testFinallyMarkers() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/finallyMarkers.kt");
doTest(fileName);
}
@TestMetadata("inlineReturnsNothing1.kt")
public void testInlineReturnsNothing1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/inlineReturnsNothing1.kt");