Expand default parameters conditions on inlining default function
#KT-14564 Fixed #KT-10848 Fixed #KT-12497 Fixed
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -32,7 +32,7 @@ class DefaultCallArgs(val size: Int) {
|
||||
bits.set(index)
|
||||
}
|
||||
|
||||
fun toInts(): List<Int> {
|
||||
private fun toInts(): List<Int> {
|
||||
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()
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -101,6 +101,10 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
private Runnable delayedHiddenWriting;
|
||||
|
||||
private List<Integer> 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);
|
||||
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
|
||||
@@ -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<Int>, 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<VarInsnNode>().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<AbstractInsnNode>()
|
||||
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<Int>): Boolean {
|
||||
val varIndex = variable.`var`
|
||||
return maskStartIndex <= varIndex && varIndex < maskStartIndex + masks.size
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
+66
@@ -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"
|
||||
}
|
||||
+70
@@ -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"
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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
|
||||
+15
@@ -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
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
+39
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user