Don't generate default arguments for inline call
This commit is contained in:
@@ -64,7 +64,7 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
||||
|
||||
@Override
|
||||
protected void generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
||||
callGenerator.putValueIfNeeded(valueParameterTypes.get(i), createDefaulValue(valueParameterTypes.get(i)));
|
||||
callGenerator.putValueIfNeeded(valueParameterTypes.get(i), createDefaulValue(valueParameterTypes.get(i)), ValueKind.DEFAULT_PARAMETER);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,8 +23,10 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
enum class ValueKind {
|
||||
GENERAL,
|
||||
DEFAULT_PARAMETER,
|
||||
DEFAULT_MASK,
|
||||
METHOD_HANDLE_IN_DEFAULT
|
||||
METHOD_HANDLE_IN_DEFAULT,
|
||||
CAPTURED
|
||||
}
|
||||
|
||||
abstract class CallGenerator {
|
||||
|
||||
@@ -414,7 +414,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
defaultSourceMapper.setCallSiteMarker(new CallSiteMarker(codegen.getLastLineNumber()));
|
||||
MethodNode node = nodeAndSmap.getNode();
|
||||
if (callDefault) {
|
||||
MethodInlinerUtilKt.expandMaskConditions(node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex);
|
||||
MethodInlinerUtilKt.expandMaskConditionsAndUpdateVariableNodes(node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex);
|
||||
}
|
||||
ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node);
|
||||
generateClosuresBodies();
|
||||
@@ -674,11 +674,17 @@ public class InlineCodegen extends CallGenerator {
|
||||
@NotNull Type type,
|
||||
@NotNull StackValue stackValue,
|
||||
int capturedParamIndex,
|
||||
int parameterIndex
|
||||
int parameterIndex,
|
||||
@NotNull ValueKind kind
|
||||
) {
|
||||
boolean isDefaultParameter = kind == ValueKind.DEFAULT_PARAMETER;
|
||||
if (!isDefaultParameter && shouldPutGeneralValue(type, stackValue)) {
|
||||
stackValue.put(type, codegen.v);
|
||||
}
|
||||
|
||||
if (!asFunctionInline && Type.VOID_TYPE != type) {
|
||||
//TODO remap only inlinable closure => otherwise we could get a lot of problem
|
||||
boolean couldBeRemapped = !shouldPutGeneralValue(type, stackValue);
|
||||
boolean couldBeRemapped = !shouldPutGeneralValue(type, stackValue) && kind != ValueKind.DEFAULT_PARAMETER;
|
||||
StackValue remappedValue = couldBeRemapped ? stackValue : null;
|
||||
|
||||
ParameterInfo info;
|
||||
@@ -691,7 +697,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
info = invocationParamBuilder.addNextValueParameter(type, false, remappedValue, parameterIndex);
|
||||
}
|
||||
|
||||
recordParameterValueInLocalVal(false, info);
|
||||
recordParameterValueInLocalVal(false, isDefaultParameter, info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -725,7 +731,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
return true;
|
||||
}
|
||||
|
||||
private Runnable recordParameterValueInLocalVal(boolean delayedWritingToLocals, @NotNull ParameterInfo... infos) {
|
||||
private Runnable recordParameterValueInLocalVal(boolean delayedWritingToLocals, boolean skipStore, @NotNull ParameterInfo... infos) {
|
||||
int[] index = new int[infos.length];
|
||||
for (int i = 0; i < infos.length; i++) {
|
||||
ParameterInfo info = infos[i];
|
||||
@@ -743,7 +749,9 @@ public class InlineCodegen extends CallGenerator {
|
||||
if (!info.isSkippedOrRemapped()) {
|
||||
Type type = info.type;
|
||||
StackValue.Local local = StackValue.local(index[i], type);
|
||||
local.store(StackValue.onStack(type), codegen.v);
|
||||
if (!skipStore) {
|
||||
local.store(StackValue.onStack(type), codegen.v);
|
||||
}
|
||||
if (info instanceof CapturedParamInfo) {
|
||||
info.setRemapValue(local);
|
||||
((CapturedParamInfo) info).setSynthetic(true);
|
||||
@@ -773,7 +781,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
invocationParamBuilder.markValueParametersStart();
|
||||
List<ParameterInfo> hiddenParameters = invocationParamBuilder.buildParameters().getParameters();
|
||||
|
||||
delayedHiddenWriting = recordParameterValueInLocalVal(justProcess, hiddenParameters.toArray(new ParameterInfo[hiddenParameters.size()]));
|
||||
delayedHiddenWriting = recordParameterValueInLocalVal(justProcess, false, hiddenParameters.toArray(new ParameterInfo[hiddenParameters.size()]));
|
||||
}
|
||||
|
||||
private void leaveTemps() {
|
||||
@@ -924,11 +932,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
assert maskValues.isEmpty() : "Additional default call arguments should be last ones, but " + value;
|
||||
|
||||
if (shouldPutGeneralValue(parameterType, value)) {
|
||||
value.put(parameterType, codegen.v);
|
||||
}
|
||||
|
||||
putArgumentOrCapturedToLocalVal(parameterType, value, -1, index);
|
||||
putArgumentOrCapturedToLocalVal(parameterType, value, -1, index, kind);
|
||||
}
|
||||
|
||||
private boolean processDefaultMaskOrMethodHandler(@NotNull StackValue value, @NotNull ValueKind kind) {
|
||||
@@ -953,10 +957,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
@Override
|
||||
public void putCapturedValueOnStack(@NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex) {
|
||||
if (shouldPutGeneralValue(stackValue.type, stackValue)) {
|
||||
stackValue.put(stackValue.type, codegen.v);
|
||||
}
|
||||
putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex, paramIndex);
|
||||
putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex, paramIndex, ValueKind.CAPTURED);
|
||||
}
|
||||
|
||||
private void generateAndInsertFinallyBlocks(
|
||||
|
||||
@@ -89,14 +89,17 @@ 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) {
|
||||
fun expandMaskConditionsAndUpdateVariableNodes(node: MethodNode, maskStartIndex: Int, masks: List<Int>, methodHandlerIndex: Int) {
|
||||
class Condition(mask: Int, constant: Int, val maskInstruction: VarInsnNode, val jumpInstruction: JumpInsnNode, val varIndex: Int) {
|
||||
val expandNotDelete = mask and constant != 0
|
||||
}
|
||||
fun isMaskIndex(varIndex: Int): Boolean {
|
||||
return maskStartIndex <= varIndex && varIndex < maskStartIndex + masks.size
|
||||
}
|
||||
|
||||
val maskProcessingHeader = node.instructions.asSequence().takeWhile {
|
||||
if (it is VarInsnNode) {
|
||||
if (isMaskIndex(it, maskStartIndex, masks)) {
|
||||
if (isMaskIndex(it.`var`)) {
|
||||
/*if slot for default mask is updated than we occurred in actual function body*/
|
||||
return@takeWhile it.opcode == Opcodes.ILOAD
|
||||
}
|
||||
@@ -108,14 +111,16 @@ fun expandMaskConditions(node: MethodNode, maskStartIndex: Int, masks: List<Int>
|
||||
}
|
||||
|
||||
val conditions = maskProcessingHeader.filterIsInstance<VarInsnNode>().mapNotNull {
|
||||
if (isMaskIndex(it, maskStartIndex, masks) &&
|
||||
if (isMaskIndex(it.`var`) &&
|
||||
it.next?.next?.opcode == Opcodes.IAND &&
|
||||
it.next.next.next?.opcode == Opcodes.IFEQ) {
|
||||
val jumpInstruction = it.next?.next?.next as JumpInsnNode
|
||||
Condition(
|
||||
masks[it.`var` - maskStartIndex],
|
||||
InlineCodegenUtil.getConstant(it.next),
|
||||
it,
|
||||
it.next?.next?.next as JumpInsnNode
|
||||
jumpInstruction,
|
||||
(jumpInstruction.label.previous as VarInsnNode).`var`
|
||||
)
|
||||
}
|
||||
else if (isMethodHandleIndex(methodHandlerIndex, it) &&
|
||||
@@ -123,17 +128,23 @@ fun expandMaskConditions(node: MethodNode, maskStartIndex: Int, masks: List<Int>
|
||||
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)
|
||||
Condition(0, 0, it,it.next as JumpInsnNode, -1)
|
||||
}
|
||||
else null
|
||||
}
|
||||
|
||||
val indexToVarNode = node.localVariables?.filter { it.index < maskStartIndex }?.associateBy { it.index } ?: emptyMap()
|
||||
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)
|
||||
}
|
||||
if (it.expandNotDelete) {
|
||||
indexToVarNode[it.varIndex]?.let { varNode ->
|
||||
varNode.start = it.jumpInstruction.label
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toDelete.forEach {
|
||||
@@ -141,10 +152,4 @@ fun expandMaskConditions(node: MethodNode, maskStartIndex: Int, masks: List<Int>
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
private fun isMethodHandleIndex(methodHandlerIndex: Int, it: VarInsnNode) = methodHandlerIndex == it.`var`
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
inline fun test(p: String = "OK"): String {
|
||||
return p
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
return test()
|
||||
}
|
||||
|
||||
//mask check in test$default
|
||||
// 1 IFEQ
|
||||
|
||||
//total ifs
|
||||
// 1 IF
|
||||
|
||||
//no default argument on call site
|
||||
// 0 NULL
|
||||
|
||||
//proper variable start label: after assignment
|
||||
// 1 LOCALVARIABLE p\$iv Ljava/lang/String; L2 L3 0
|
||||
// 1 LDC "OK"\s*ASTORE 0\s*L2
|
||||
@@ -1,11 +0,0 @@
|
||||
inline fun test(p: String = "OK"): String {
|
||||
return p
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
return test()
|
||||
}
|
||||
|
||||
//mask check in test$default
|
||||
// 1 IFEQ
|
||||
// 1 IF
|
||||
+2
@@ -1,3 +1,4 @@
|
||||
//open modality to method handle check generation
|
||||
open class A {
|
||||
inline fun test(p: String = "OK"): String {
|
||||
return p
|
||||
@@ -12,4 +13,5 @@ fun box(): String {
|
||||
// 1 IFNULL
|
||||
//mask check in test$default
|
||||
// 1 IFEQ
|
||||
//total ifs
|
||||
// 2 IF
|
||||
@@ -929,29 +929,29 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination")
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class MaskElumination extends AbstractBlackBoxInlineCodegenTest {
|
||||
public static class MaskElimination extends AbstractBlackBoxInlineCodegenTest {
|
||||
@TestMetadata("32Parameters.kt")
|
||||
public void test32Parameters() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/32Parameters.kt");
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/32Parameters.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("33Parameters.kt")
|
||||
public void test33Parameters() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/33Parameters.kt");
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/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);
|
||||
public void testAllFilesPresentInMaskElimination() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/defaultValues/maskElimination"), 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");
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1091,15 +1091,15 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("maskElumination.kt")
|
||||
public void testMaskElumination() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/defaultArguments/maskElumination.kt");
|
||||
@TestMetadata("maskAndArgumentElimination.kt")
|
||||
public void testMaskAndArgumentElimination() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/defaultArguments/maskAndArgumentElimination.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("methodHandlerElumination.kt")
|
||||
public void testMethodHandlerElumination() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/defaultArguments/methodHandlerElumination.kt");
|
||||
@TestMetadata("methodHandlerElimination.kt")
|
||||
public void testMethodHandlerElimination() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/defaultArguments/methodHandlerElimination.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -929,29 +929,29 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination")
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class MaskElumination extends AbstractCompileKotlinAgainstInlineKotlinTest {
|
||||
public static class MaskElimination extends AbstractCompileKotlinAgainstInlineKotlinTest {
|
||||
@TestMetadata("32Parameters.kt")
|
||||
public void test32Parameters() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/32Parameters.kt");
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/32Parameters.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("33Parameters.kt")
|
||||
public void test33Parameters() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/33Parameters.kt");
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/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);
|
||||
public void testAllFilesPresentInMaskElimination() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/defaultValues/maskElimination"), 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");
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user