From 02cc5f6bc18878c46e8796feb2cf552a5f9c48a6 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Wed, 26 Apr 2017 16:08:47 +0200 Subject: [PATCH] Expand default parameters conditions on inlining default function #KT-14564 Fixed #KT-10848 Fixed #KT-12497 Fixed --- .../jetbrains/kotlin/codegen/CallGenerator.kt | 18 ++++- .../kotlin/codegen/DefaultCallArgs.kt | 6 +- .../jetbrains/kotlin/codegen/StackValue.java | 4 +- .../kotlin/codegen/inline/InlineCodegen.java | 53 +++++++++++--- .../inline/InlineCodegenForDefaultBody.kt | 2 +- .../codegen/inline/MethodInlinerUtil.kt | 66 ++++++++++++++++- .../boxInline/defaultValues/kt14564.kt | 36 ++++++++++ .../boxInline/defaultValues/kt14564_2.kt | 33 +++++++++ .../maskElumination/32Parameters.kt | 66 +++++++++++++++++ .../maskElumination/33Parameters.kt | 70 +++++++++++++++++++ .../defaultValues/maskElumination/simple.kt | 36 ++++++++++ .../defaultArguments/maskElumination.kt | 11 +++ .../methodHandlerElumination.kt | 15 ++++ .../BlackBoxInlineCodegenTestGenerated.java | 39 +++++++++++ .../codegen/BytecodeTextTestGenerated.java | 12 ++++ ...otlinAgainstInlineKotlinTestGenerated.java | 39 +++++++++++ 16 files changed, 483 insertions(+), 23 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/defaultValues/kt14564.kt create mode 100644 compiler/testData/codegen/boxInline/defaultValues/kt14564_2.kt create mode 100644 compiler/testData/codegen/boxInline/defaultValues/maskElumination/32Parameters.kt create mode 100644 compiler/testData/codegen/boxInline/defaultValues/maskElumination/33Parameters.kt create mode 100644 compiler/testData/codegen/boxInline/defaultValues/maskElumination/simple.kt create mode 100644 compiler/testData/codegen/bytecodeText/defaultArguments/maskElumination.kt create mode 100644 compiler/testData/codegen/bytecodeText/defaultArguments/methodHandlerElumination.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt index 964890439f0..58f860612f4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt @@ -21,6 +21,12 @@ import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.org.objectweb.asm.Type +enum class ValueKind { + GENERAL, + DEFAULT_MASK, + METHOD_HANDLE_IN_DEFAULT +} + abstract class CallGenerator { internal class DefaultCallGenerator(private val codegen: ExpressionCodegen) : CallGenerator() { @@ -67,8 +73,7 @@ abstract class CallGenerator { stackValue.put(stackValue.type, codegen.v) } - override fun putValueIfNeeded( - parameterType: Type, value: StackValue) { + override fun putValueIfNeeded(parameterType: Type, value: StackValue, kind: ValueKind) { value.put(value.type, codegen.v) } @@ -117,9 +122,16 @@ abstract class CallGenerator { parameterType: Type, parameterIndex: Int) + fun putValueIfNeeded( + parameterType: Type, + value: StackValue) { + putValueIfNeeded(parameterType, value, ValueKind.GENERAL) + } + abstract fun putValueIfNeeded( parameterType: Type, - value: StackValue) + value: StackValue, + kind: ValueKind) abstract fun putCapturedValueOnStack( stackValue: StackValue, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultCallArgs.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultCallArgs.kt index 321e6c7a319..3579e8a7c81 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultCallArgs.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultCallArgs.kt @@ -32,7 +32,7 @@ class DefaultCallArgs(val size: Int) { bits.set(index) } - fun toInts(): List { + private fun toInts(): List { if (bits.isEmpty || size == 0) { return emptyList() } @@ -56,11 +56,11 @@ class DefaultCallArgs(val size: Int) { val toInts = toInts() if (!toInts.isEmpty()) { for (mask in toInts) { - callGenerator.putValueIfNeeded(Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE)) + callGenerator.putValueIfNeeded(Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE), ValueKind.DEFAULT_MASK) } val parameterType = if (isConstructor) AsmTypes.DEFAULT_CONSTRUCTOR_MARKER else AsmTypes.OBJECT_TYPE - callGenerator.putValueIfNeeded(parameterType, StackValue.constant(null, parameterType)) + callGenerator.putValueIfNeeded(parameterType, StackValue.constant(null, parameterType), ValueKind.METHOD_HANDLE_IN_DEFAULT) } return toInts.isNotEmpty() } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index 539496bf411..5a365f52779 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -741,9 +741,9 @@ public abstract class StackValue { } } - private static class Constant extends StackValue { + public static class Constant extends StackValue { @Nullable - private final Object value; + public final Object value; public Constant(@Nullable Object value, Type type) { super(type, false); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index 988ed0e974a..da018ac5823 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -101,6 +101,10 @@ public class InlineCodegen extends CallGenerator { private Runnable delayedHiddenWriting; + private List maskValues = new ArrayList<>(); + private int maskStartIndex = -1; + private int methodHandleInDefaultMethodIndex = -1; + public InlineCodegen( @NotNull ExpressionCodegen codegen, @NotNull GenerationState state, @@ -177,7 +181,7 @@ public class InlineCodegen extends CallGenerator { SMAPAndMethodNode nodeAndSmap = null; try { nodeAndSmap = createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, resolvedCall); - endCall(inlineCall(nodeAndSmap)); + endCall(inlineCall(nodeAndSmap, callDefault)); } catch (CompilationException e) { throw e; @@ -378,7 +382,7 @@ public class InlineCodegen extends CallGenerator { implementationOwner.getInternalName() ); if (!(element instanceof KtNamedFunction)) { - throw new IllegalStateException("Propertiy accessors with default parameters not supported " + callableDescriptor); + throw new IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor); } FunctionCodegen.generateDefaultImplBody( methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT, @@ -404,11 +408,14 @@ public class InlineCodegen extends CallGenerator { } @NotNull - private InlineResult inlineCall(@NotNull SMAPAndMethodNode nodeAndSmap) { + private InlineResult inlineCall(@NotNull SMAPAndMethodNode nodeAndSmap, boolean callDefault) { assert delayedHiddenWriting == null : "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'"; DefaultSourceMapper defaultSourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper(); defaultSourceMapper.setCallSiteMarker(new CallSiteMarker(codegen.getLastLineNumber())); MethodNode node = nodeAndSmap.getNode(); + if (callDefault) { + MethodInlinerUtilKt.expandMaskConditions(node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex); + } ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node); generateClosuresBodies(); @@ -676,7 +683,7 @@ public class InlineCodegen extends CallGenerator { ) { if (!asFunctionInline && Type.VOID_TYPE != type) { //TODO remap only inlinable closure => otherwise we could get a lot of problem - boolean couldBeRemapped = !shouldPutValue(type, stackValue); + boolean couldBeRemapped = !shouldPutGeneralValue(type, stackValue); StackValue remappedValue = couldBeRemapped ? stackValue : null; ParameterInfo info; @@ -694,7 +701,7 @@ public class InlineCodegen extends CallGenerator { } /*descriptor is null for captured vars*/ - private static boolean shouldPutValue(@NotNull Type type, @Nullable StackValue stackValue) { + private static boolean shouldPutGeneralValue(@NotNull Type type, @Nullable StackValue stackValue) { if (stackValue == null) { //default or vararg return true; @@ -899,7 +906,7 @@ public class InlineCodegen extends CallGenerator { } else { StackValue value = codegen.gen(argumentExpression); - putValueIfNeeded(parameterType, value, valueParameterDescriptor.getIndex()); + putValueIfNeeded(parameterType, value, valueParameterDescriptor.getIndex(), ValueKind.GENERAL); } } @@ -918,20 +925,44 @@ public class InlineCodegen extends CallGenerator { } @Override - public void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value) { - putValueIfNeeded(parameterType, value, -1); + public void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value, @NotNull ValueKind kind) { + putValueIfNeeded(parameterType, value, -1, kind); } - private void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value, int index) { - if (shouldPutValue(parameterType, value)) { + private void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value, int index, @NotNull ValueKind kind) { + if (processDefaultMaskOrMethodHandler(value, kind)) return; + + assert maskValues.isEmpty() : "Additional default call arguments should be last ones, but " + value; + + if (shouldPutGeneralValue(parameterType, value)) { value.put(parameterType, codegen.v); } afterParameterPut(parameterType, value, index); } + private boolean processDefaultMaskOrMethodHandler(@NotNull StackValue value, @NotNull ValueKind kind) { + if (kind != ValueKind.DEFAULT_MASK && kind != ValueKind.METHOD_HANDLE_IN_DEFAULT) { + return false; + } + assert value instanceof StackValue.Constant : "Additional default method argument should be constant, but " + value; + Object constantValue = ((StackValue.Constant) value).value; + if (kind == ValueKind.DEFAULT_MASK) { + assert constantValue instanceof Integer : "Mask should be of Integer type, but " + constantValue; + maskValues.add((Integer) constantValue); + if (maskStartIndex == -1) { + maskStartIndex = invocationParamBuilder.getNextParameterOffset(); + } + } + else { + assert constantValue == null : "Additional method handle for default argument should be null, but " + constantValue; + methodHandleInDefaultMethodIndex = maskStartIndex + maskValues.size(); + } + return true; + } + @Override public void putCapturedValueOnStack(@NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex) { - if (shouldPutValue(stackValue.type, stackValue)) { + if (shouldPutGeneralValue(stackValue.type, stackValue)) { stackValue.put(stackValue.type, codegen.v); } putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex, paramIndex); 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 f8aa6c429f7..53031291535 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt @@ -95,7 +95,7 @@ class InlineCodegenForDefaultBody( throw UnsupportedOperationException("Shouldn't be called") } - override fun putValueIfNeeded(parameterType: Type, value: StackValue) { + override fun putValueIfNeeded(parameterType: Type, value: StackValue, kind: ValueKind) { //original method would be inlined directly into default impl body without any inline magic //so we no need to load variables on stack to further method call } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt index 073758f7d46..3760f557dc5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInlinerUtil.kt @@ -16,12 +16,12 @@ package org.jetbrains.kotlin.codegen.inline +import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence +import org.jetbrains.kotlin.codegen.optimization.common.asSequence import org.jetbrains.kotlin.codegen.optimization.fixStack.top import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.org.objectweb.asm.Opcodes -import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode -import org.jetbrains.org.objectweb.asm.tree.InsnList -import org.jetbrains.org.objectweb.asm.tree.VarInsnNode +import org.jetbrains.org.objectweb.asm.tree.* import org.jetbrains.org.objectweb.asm.tree.analysis.Frame import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue @@ -88,3 +88,63 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions( } fun SourceValue.singleOrNullInsn() = insns.singleOrNull() + +fun expandMaskConditions(node: MethodNode, maskStartIndex: Int, masks: List, methodHandlerIndex: Int) { + class Condition(mask: Int, constant: Int, val maskInstruction: VarInsnNode, val jumpInstruction: JumpInsnNode) { + val expandNotDelete = mask and constant != 0 + } + + val maskProcessingHeader = node.instructions.asSequence().takeWhile { + if (it is VarInsnNode) { + if (isMaskIndex(it, maskStartIndex, masks)) { + /*if slot for default mask is updated than we occurred in actual function body*/ + return@takeWhile it.opcode == Opcodes.ILOAD + } + else if (isMethodHandleIndex(methodHandlerIndex, it)) { + return@takeWhile it.opcode == Opcodes.ALOAD + } + } + true + } + + val conditions = maskProcessingHeader.filterIsInstance().mapNotNull { + if (isMaskIndex(it, maskStartIndex, masks) && + it.next?.next?.opcode == Opcodes.IAND && + it.next.next.next?.opcode == Opcodes.IFEQ) { + Condition( + masks[it.`var` - maskStartIndex], + InlineCodegenUtil.getConstant(it.next), + it, + it.next?.next?.next as JumpInsnNode + ) + } + else if (isMethodHandleIndex(methodHandlerIndex, it) && + it.next?.opcode == Opcodes.IFNULL && + it.next.next?.opcode == Opcodes.NEW) { + //Always delete method handle for now + //This logic should be updated when method handles would be supported + Condition(0, 0, it,it.next as JumpInsnNode) + } + else null + } + + val toDelete = arrayListOf() + conditions.forEach { + val jumpInstruction = it.jumpInstruction + InsnSequence(it.maskInstruction, (if (it.expandNotDelete) jumpInstruction.next else jumpInstruction.label)).forEach { + toDelete.add(it) + } + } + + toDelete.forEach { + node.instructions.remove(it) + } +} + +private fun isMethodHandleIndex(methodHandlerIndex: Int, it: VarInsnNode) = methodHandlerIndex == it.`var` + +private fun isMaskIndex(variable: VarInsnNode, maskStartIndex: Int, masks: List): Boolean { + val varIndex = variable.`var` + return maskStartIndex <= varIndex && varIndex < maskStartIndex + masks.size +} + diff --git a/compiler/testData/codegen/boxInline/defaultValues/kt14564.kt b/compiler/testData/codegen/boxInline/defaultValues/kt14564.kt new file mode 100644 index 00000000000..c9a422774fc --- /dev/null +++ b/compiler/testData/codegen/boxInline/defaultValues/kt14564.kt @@ -0,0 +1,36 @@ +// FILE: 1.kt +//NO_CHECK_LAMBDA_INLINING + +package test + +object TimeUtil { + inline fun waitForEx(retryWait: Int = 200, + action: () -> Boolean) { + var now = 1L + if (now++ <= 3) { + action() + } + + } + +} + +// FILE: 2.kt + +import test.* + +var result = "fail" + +fun box(): String { + TimeUtil.waitForEx( + action = { + try { + result = "OK" + true + } + catch (t: Throwable) { + false + } + }) + return result +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/defaultValues/kt14564_2.kt b/compiler/testData/codegen/boxInline/defaultValues/kt14564_2.kt new file mode 100644 index 00000000000..bc0a465bd53 --- /dev/null +++ b/compiler/testData/codegen/boxInline/defaultValues/kt14564_2.kt @@ -0,0 +1,33 @@ +// FILE: 1.kt + +package test + +var result = "fail" + +object TimeUtil { + + fun waitForAssert(z: String) { + waitForEx( + action = { + result = z + result + }) + } + + inline fun waitForEx(retryWait: Int = 200, + action: () -> String) { + var now = 1L + now++ + action() + } + +} + +// FILE: 2.kt + +import test.* + +fun box(): String { + TimeUtil.waitForAssert("OK") + return result +} diff --git a/compiler/testData/codegen/boxInline/defaultValues/maskElumination/32Parameters.kt b/compiler/testData/codegen/boxInline/defaultValues/maskElumination/32Parameters.kt new file mode 100644 index 00000000000..5ec5e8be2a5 --- /dev/null +++ b/compiler/testData/codegen/boxInline/defaultValues/maskElumination/32Parameters.kt @@ -0,0 +1,66 @@ +// FILE: 1.kt + +package test + +fun calc() = "OK" + +inline fun test( + p1: String = "1", + p2: String = "2", + p3: String = "3", + p4: String = "4", + p5: String = "5", + p6: String = "6", + p7: String = "7", + p8: String = "8", + p9: String = "9", + p10: String = "10", + p11: String = "11", + p12: String = "12", + p13: String = "13", + p14: String = "14", + p15: String = "15", + p16: String = "16", + p17: String = "17", + p18: String = "18", + p19: String = "19", + p20: String = "20", + p21: String = "21", + p22: String = "22", + p23: String = "23", + p24: String = "24", + p25: String = "25", + p26: String = "26", + p27: String = "27", + p28: String = "28", + p29: String = "29", + p30: String = "30", + p31: String = "31", + p32: String = "32" +): String { + return p1 + " " + p2 + " " + p3 + " " + p4 + " " + p5 + " " + p6 + " " + + p7 + " " + p8 + " " + p9 + " " + p10 + " " + p11 + " " + p12 + " " + p13 + " " + p14 + " " + + p15 + " " + p16 + " " + p17 + " " + p18 + " " + p19 + " " + p20 + " " + p21 + " " + + p22 + " " + p23 + " " + p24 + " " + p25 + " " + p26 + " " + p27 + " " + p28 + " " + + p29 + " " + p30 + " " + p31 + " " + p32 +} + +// FILE: 2.kt + +import test.* + +fun box(): String { + if (test() != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32") + return "fail 1: ${test()}" + + if (test(p20 = "OK") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 OK 21 22 23 24 25 26 27 28 29 30 31 32") + return "fail 2: ${test(p20 = "OK")}" + + if (test(p20 = "O", p22 = "K") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 O 21 K 23 24 25 26 27 28 29 30 31 32") + return "fail 3: ${test(p20 = "O", p22 = "K")}" + + if (test(p20 = "O", p22 = "K", p32 = "23") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 O 21 K 23 24 25 26 27 28 29 30 31 23") + return "fail 4: ${test(p20 = "O", p22 = "K", p32 = "23")}" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/defaultValues/maskElumination/33Parameters.kt b/compiler/testData/codegen/boxInline/defaultValues/maskElumination/33Parameters.kt new file mode 100644 index 00000000000..70b89a7c6d2 --- /dev/null +++ b/compiler/testData/codegen/boxInline/defaultValues/maskElumination/33Parameters.kt @@ -0,0 +1,70 @@ +// FILE: 1.kt + +package test + +fun calc() = "OK" + +inline fun test( + p1: String = "1", + p2: String = "2", + p3: String = "3", + p4: String = "4", + p5: String = "5", + p6: String = "6", + p7: String = "7", + p8: String = "8", + p9: String = "9", + p10: String = "10", + p11: String = "11", + p12: String = "12", + p13: String = "13", + p14: String = "14", + p15: String = "15", + p16: String = "16", + p17: String = "17", + p18: String = "18", + p19: String = "19", + p20: String = "20", + p21: String = "21", + p22: String = "22", + p23: String = "23", + p24: String = "24", + p25: String = "25", + p26: String = "26", + p27: String = "27", + p28: String = "28", + p29: String = "29", + p30: String = "30", + p31: String = "31", + p32: String = "32", + p33: String = "33" +): String { + return p1 + " " + p2 + " " + p3 + " " + p4 + " " + p5 + " " + p6 + " " + + p7 + " " + p8 + " " + p9 + " " + p10 + " " + p11 + " " + p12 + " " + p13 + " " + p14 + " " + + p15 + " " + p16 + " " + p17 + " " + p18 + " " + p19 + " " + p20 + " " + p21 + " " + + p22 + " " + p23 + " " + p24 + " " + p25 + " " + p26 + " " + p27 + " " + p28 + " " + + p29 + " " + p30 + " " + p31 + " " + p32 + " " + p33 +} + +// FILE: 2.kt + +import test.* + +fun box(): String { + if (test() != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33") + return "fail 1: ${test()}" + + if (test(p20 = "OK") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 OK 21 22 23 24 25 26 27 28 29 30 31 32 33") + return "fail 2: ${test(p20 = "OK")}" + + if (test(p20 = "O", p22 = "K") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 O 21 K 23 24 25 26 27 28 29 30 31 32 33") + return "fail 3: ${test(p20 = "O", p22 = "K")}" + + if (test(p20 = "O", p22 = "K", p32 = "23") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 O 21 K 23 24 25 26 27 28 29 30 31 23 33") + return "fail 4: ${test(p20 = "O", p22 = "K", p32 = "23")}" + + if (test(p20 = "O", p22 = "K", p32 = "33", p33 ="32") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 O 21 K 23 24 25 26 27 28 29 30 31 33 32") + return "fail 4: ${test(p20 = "O", p22 = "K", p32 = "33", p33 ="32")}" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/defaultValues/maskElumination/simple.kt b/compiler/testData/codegen/boxInline/defaultValues/maskElumination/simple.kt new file mode 100644 index 00000000000..bca4b1fd4a8 --- /dev/null +++ b/compiler/testData/codegen/boxInline/defaultValues/maskElumination/simple.kt @@ -0,0 +1,36 @@ +// FILE: 1.kt + +package test + +fun calc() = "OK" + +/*open modifier for method handle check in default method*/ +open class A { + inline fun test(p: String = calc()): String { + return p + } + + inline fun String.testExt(p: String = "K"): String { + return this + p + } + + fun callExt(): String { + return "O".testExt() + } + + fun callExt(arg: String): String { + return "O".testExt(arg) + } +} + +// FILE: 2.kt + +import test.* + +fun box() : String { + if (A().callExt() != "OK") return "fail 1: ${A().callExt()}" + if (A().callExt("O") != "OO") return "fail 2: ${A().callExt("O")}" + if (A().test("KK") != "KK") return "fail 3: ${A().test("KK")}" + + return A().test() +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/defaultArguments/maskElumination.kt b/compiler/testData/codegen/bytecodeText/defaultArguments/maskElumination.kt new file mode 100644 index 00000000000..05b267ba075 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/defaultArguments/maskElumination.kt @@ -0,0 +1,11 @@ +inline fun test(p: String = "OK"): String { + return p +} + +fun box() : String { + return test() +} + +//mask check in test$default +// 1 IFEQ +// 1 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/defaultArguments/methodHandlerElumination.kt b/compiler/testData/codegen/bytecodeText/defaultArguments/methodHandlerElumination.kt new file mode 100644 index 00000000000..9082e7ca737 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/defaultArguments/methodHandlerElumination.kt @@ -0,0 +1,15 @@ +open class A { + inline fun test(p: String = "OK"): String { + return p + } +} + +fun box(): String { + return A().test() +} + +//handler check in test$default +// 1 IFNULL +//mask check in test$default +// 1 IFEQ +// 2 IF \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index 7a75c2ec08c..449cbc35b62 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -905,6 +905,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo doTest(fileName); } + @TestMetadata("kt14564.kt") + public void testKt14564() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt14564.kt"); + doTest(fileName); + } + + @TestMetadata("kt14564_2.kt") + public void testKt14564_2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt14564_2.kt"); + doTest(fileName); + } + @TestMetadata("kt5685.kt") public void testKt5685() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt5685.kt"); @@ -916,6 +928,33 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/simpleDefaultMethod.kt"); doTest(fileName); } + + @TestMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class MaskElumination extends AbstractBlackBoxInlineCodegenTest { + @TestMetadata("32Parameters.kt") + public void test32Parameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/32Parameters.kt"); + doTest(fileName); + } + + @TestMetadata("33Parameters.kt") + public void test33Parameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/33Parameters.kt"); + doTest(fileName); + } + + public void testAllFilesPresentInMaskElumination() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/defaultValues/maskElumination"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/simple.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/boxInline/delegatedProperty") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 0f36883a661..3d095913d4c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -1090,6 +1090,18 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/defaultArguments/kt11962.kt"); doTest(fileName); } + + @TestMetadata("maskElumination.kt") + public void testMaskElumination() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/defaultArguments/maskElumination.kt"); + doTest(fileName); + } + + @TestMetadata("methodHandlerElumination.kt") + public void testMethodHandlerElumination() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/defaultArguments/methodHandlerElumination.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/bytecodeText/directInvoke") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 2f73120a573..4446867567c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -905,6 +905,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi doTest(fileName); } + @TestMetadata("kt14564.kt") + public void testKt14564() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt14564.kt"); + doTest(fileName); + } + + @TestMetadata("kt14564_2.kt") + public void testKt14564_2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt14564_2.kt"); + doTest(fileName); + } + @TestMetadata("kt5685.kt") public void testKt5685() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt5685.kt"); @@ -916,6 +928,33 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/simpleDefaultMethod.kt"); doTest(fileName); } + + @TestMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class MaskElumination extends AbstractCompileKotlinAgainstInlineKotlinTest { + @TestMetadata("32Parameters.kt") + public void test32Parameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/32Parameters.kt"); + doTest(fileName); + } + + @TestMetadata("33Parameters.kt") + public void test33Parameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/33Parameters.kt"); + doTest(fileName); + } + + public void testAllFilesPresentInMaskElumination() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/defaultValues/maskElumination"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/simple.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/boxInline/delegatedProperty")