Added assertion for super call with default arguments in function default impl body
This commit is contained in:
@@ -22,6 +22,7 @@ import com.intellij.util.ArrayUtil;
|
|||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
|
import kotlin.text.StringsKt;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
||||||
@@ -672,7 +673,7 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen);
|
generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod);
|
||||||
endVisit(mv, "default method", getSourceFromDescriptor(functionDescriptor));
|
endVisit(mv, "default method", getSourceFromDescriptor(functionDescriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,7 +694,8 @@ public class FunctionCodegen {
|
|||||||
@NotNull MethodVisitor mv,
|
@NotNull MethodVisitor mv,
|
||||||
@NotNull DefaultParameterValueLoader loadStrategy,
|
@NotNull DefaultParameterValueLoader loadStrategy,
|
||||||
@Nullable KtNamedFunction function,
|
@Nullable KtNamedFunction function,
|
||||||
@NotNull MemberCodegen<?> parentCodegen
|
@NotNull MemberCodegen<?> parentCodegen,
|
||||||
|
@NotNull Method defaultMethod
|
||||||
) {
|
) {
|
||||||
GenerationState state = parentCodegen.state;
|
GenerationState state = parentCodegen.state;
|
||||||
JvmMethodSignature signature = state.getTypeMapper().mapSignature(functionDescriptor, methodContext.getContextKind());
|
JvmMethodSignature signature = state.getTypeMapper().mapSignature(functionDescriptor, methodContext.getContextKind());
|
||||||
@@ -705,6 +707,9 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
CallGenerator generator = codegen.getOrCreateCallGeneratorForDefaultImplBody(functionDescriptor, function);
|
CallGenerator generator = codegen.getOrCreateCallGeneratorForDefaultImplBody(functionDescriptor, function);
|
||||||
|
|
||||||
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
|
genDefaultSuperCallCheckIfNeeded(iv, defaultMethod);
|
||||||
|
|
||||||
loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator);
|
loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator);
|
||||||
|
|
||||||
List<JvmMethodParameterSignature> mappedParameters = signature.getValueParameters();
|
List<JvmMethodParameterSignature> mappedParameters = signature.getValueParameters();
|
||||||
@@ -714,8 +719,6 @@ public class FunctionCodegen {
|
|||||||
capturedArgumentsCount++;
|
capturedArgumentsCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
|
||||||
|
|
||||||
int maskIndex = 0;
|
int maskIndex = 0;
|
||||||
List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
|
List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
|
||||||
for (int index = 0; index < valueParameters.size(); index++) {
|
for (int index = 0; index < valueParameters.size(); index++) {
|
||||||
@@ -748,6 +751,22 @@ public class FunctionCodegen {
|
|||||||
iv.areturn(signature.getReturnType());
|
iv.areturn(signature.getReturnType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void genDefaultSuperCallCheckIfNeeded(@NotNull InstructionAdapter iv, @NotNull Method defaultMethod) {
|
||||||
|
String defaultMethodName = defaultMethod.getName();
|
||||||
|
if ("<init>".equals(defaultMethodName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Label end = new Label();
|
||||||
|
int handleIndex = (Type.getArgumentsAndReturnSizes(defaultMethod.getDescriptor()) >> 2) - 2; /*-1 for this, and -1 for handle*/
|
||||||
|
iv.load(handleIndex, OBJECT_TYPE);
|
||||||
|
iv.ifnull(end);
|
||||||
|
AsmUtil.genThrow(iv,
|
||||||
|
"java/lang/UnsupportedOperationException",
|
||||||
|
"Super calls with default arguments not supported in this target, function: " +
|
||||||
|
StringsKt.substringBeforeLast(defaultMethodName, JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodName));
|
||||||
|
iv.visitLabel(end);
|
||||||
|
}
|
||||||
|
|
||||||
private void generateOldDefaultForFun(
|
private void generateOldDefaultForFun(
|
||||||
Method newDefaultMethod,
|
Method newDefaultMethod,
|
||||||
JvmDeclarationOrigin origin,
|
JvmDeclarationOrigin origin,
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
implementationOwner.getInternalName());
|
implementationOwner.getInternalName());
|
||||||
FunctionCodegen.generateDefaultImplBody(
|
FunctionCodegen.generateDefaultImplBody(
|
||||||
methodContext, functionDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
|
methodContext, functionDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
|
||||||
inliningFunction, parentCodegen
|
inliningFunction, parentCodegen, asmMethod
|
||||||
);
|
);
|
||||||
smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
|
smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
fun def(i: Int = 0): Int {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box():String {
|
||||||
|
val clazz = Class.forName("SuperCallCheckKt")
|
||||||
|
|
||||||
|
val method = clazz.getMethod("def\$default", Int::class.java, Int::class.java, Any::class.java)
|
||||||
|
val result = method.invoke(null, -1, 1, null)
|
||||||
|
|
||||||
|
if (result != 0) return "fail 1: $result"
|
||||||
|
|
||||||
|
var failed = false
|
||||||
|
try {
|
||||||
|
method.invoke(null, -1, 1, "fail")
|
||||||
|
} catch(e: Exception) {
|
||||||
|
val cause = e.cause
|
||||||
|
if (cause is java.lang.UnsupportedOperationException &&
|
||||||
|
cause.message!!.startsWith("Super calls")) {
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (!failed) "fail" else "OK"
|
||||||
|
}
|
||||||
+2
-2
@@ -8,6 +8,6 @@ class A {
|
|||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Test argument reordering when call site argument order differs from declaration one
|
// Test argument reordering when call site argument order differs from declaration one: 18 + 1 for super call check
|
||||||
// 18 LOAD
|
// 19 LOAD
|
||||||
// 5 STORE
|
// 5 STORE
|
||||||
+2
-2
@@ -7,6 +7,6 @@ class A {
|
|||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Test there is no argument reordering when call site argument order same as declaration one
|
// Test there is no argument reordering when call site argument order same as declaration one: 15 + 1 for super call check
|
||||||
// 15 LOAD
|
// 16 LOAD
|
||||||
// 2 STORE
|
// 2 STORE
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
class A (i: Int = 0)
|
||||||
|
|
||||||
|
// 0 ATHROW
|
||||||
@@ -233,6 +233,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("noSuperCheckInDefaultConstuctor.kt")
|
||||||
|
public void testNoSuperCheckInDefaultConstuctor() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/noSuperCheckInDefaultConstuctor.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noWrapperForMethodReturningPrimitive.kt")
|
@TestMetadata("noWrapperForMethodReturningPrimitive.kt")
|
||||||
public void testNoWrapperForMethodReturningPrimitive() throws Exception {
|
public void testNoWrapperForMethodReturningPrimitive() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/noWrapperForMethodReturningPrimitive.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/noWrapperForMethodReturningPrimitive.kt");
|
||||||
|
|||||||
+6
@@ -1450,6 +1450,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
doTestWithStdlib(fileName);
|
doTestWithStdlib(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("superCallCheck.kt")
|
||||||
|
public void testSuperCallCheck() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/defaultArguments/superCallCheck.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/defaultArguments/constructor")
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/defaultArguments/constructor")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user