Generate INSTANCEOF barrier in bridges for Collection.contains
This commit is contained in:
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
|||||||
import org.jetbrains.kotlin.backend.common.bridges.BridgesPackage;
|
import org.jetbrains.kotlin.backend.common.bridges.BridgesPackage;
|
||||||
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithOnlyTargetedAnnotations;
|
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithOnlyTargetedAnnotations;
|
||||||
import org.jetbrains.kotlin.codegen.context.*;
|
import org.jetbrains.kotlin.codegen.context.*;
|
||||||
|
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics;
|
||||||
import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor;
|
import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||||
@@ -54,6 +55,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||||
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||||
import org.jetbrains.org.objectweb.asm.Label;
|
import org.jetbrains.org.objectweb.asm.Label;
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||||
@@ -815,6 +817,8 @@ public class FunctionCodegen {
|
|||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ImplementationBodyCodegen.markLineNumberForSyntheticFunction(owner.getThisDescriptor(), iv);
|
ImplementationBodyCodegen.markLineNumberForSyntheticFunction(owner.getThisDescriptor(), iv);
|
||||||
|
|
||||||
|
generateInstanceOfBarrierIfNeeded(iv, descriptor, bridge, delegateTo);
|
||||||
|
|
||||||
iv.load(0, OBJECT_TYPE);
|
iv.load(0, OBJECT_TYPE);
|
||||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||||
StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
|
StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
|
||||||
@@ -822,7 +826,6 @@ public class FunctionCodegen {
|
|||||||
reg += argTypes[i].getSize();
|
reg += argTypes[i].getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (superCallNeeded) {
|
if (superCallNeeded) {
|
||||||
ClassDescriptor parentClass = getSuperClassDescriptor((ClassDescriptor) descriptor.getContainingDeclaration());
|
ClassDescriptor parentClass = getSuperClassDescriptor((ClassDescriptor) descriptor.getContainingDeclaration());
|
||||||
assert parentClass != null;
|
assert parentClass != null;
|
||||||
@@ -839,6 +842,56 @@ public class FunctionCodegen {
|
|||||||
endVisit(mv, "bridge method", origin);
|
endVisit(mv, "bridge method", origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void generateInstanceOfBarrierIfNeeded(
|
||||||
|
@NotNull InstructionAdapter iv,
|
||||||
|
@NotNull FunctionDescriptor descriptor,
|
||||||
|
@NotNull Method bridge,
|
||||||
|
@NotNull Method delegateTo
|
||||||
|
) {
|
||||||
|
if (BuiltinsPropertiesUtilKt.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor) == null) return;
|
||||||
|
|
||||||
|
assert descriptor.getValueParameters().size() == 1 : "Should be descriptor with one value parameter, but found: " + descriptor;
|
||||||
|
|
||||||
|
iv.load(1, OBJECT_TYPE);
|
||||||
|
|
||||||
|
JetType jetType = descriptor.getValueParameters().get(0).getType();
|
||||||
|
|
||||||
|
// TODO: reuse logic from ExpressionCodegen
|
||||||
|
if (jetType.isMarkedNullable()) {
|
||||||
|
Label nope = new Label();
|
||||||
|
Label end = new Label();
|
||||||
|
|
||||||
|
iv.dup();
|
||||||
|
iv.ifnull(nope);
|
||||||
|
TypeIntrinsics.instanceOf(
|
||||||
|
iv,
|
||||||
|
jetType,
|
||||||
|
boxType(delegateTo.getArgumentTypes()[0])
|
||||||
|
);
|
||||||
|
iv.goTo(end);
|
||||||
|
iv.mark(nope);
|
||||||
|
iv.pop();
|
||||||
|
iv.iconst(1);
|
||||||
|
iv.mark(end);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TypeIntrinsics.instanceOf(
|
||||||
|
iv,
|
||||||
|
jetType,
|
||||||
|
boxType(delegateTo.getArgumentTypes()[0])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Label afterBarrier = new Label();
|
||||||
|
|
||||||
|
iv.ifne(afterBarrier);
|
||||||
|
|
||||||
|
StackValue.none().put(bridge.getReturnType(), iv);
|
||||||
|
iv.areturn(bridge.getReturnType());
|
||||||
|
|
||||||
|
iv.visitLabel(afterBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
public void genDelegate(@NotNull FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
|
public void genDelegate(@NotNull FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
|
||||||
genDelegate(functionDescriptor, overriddenDescriptor.getOriginal(),
|
genDelegate(functionDescriptor, overriddenDescriptor.getOriginal(),
|
||||||
(ClassDescriptor) overriddenDescriptor.getContainingDeclaration(), field);
|
(ClassDescriptor) overriddenDescriptor.getContainingDeclaration(), field);
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
class StrList : List<String?> {
|
||||||
|
override val size: Int
|
||||||
|
get() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun contains(o: String?) = o == null || o == "abc"
|
||||||
|
|
||||||
|
override fun iterator(): Iterator<String> {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun containsAll(c: Collection<String?>) = false
|
||||||
|
override fun get(index: Int): String {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun indexOf(o: Any?): Int {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun lastIndexOf(o: Any?): Int {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun listIterator(): ListIterator<String?> {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun listIterator(index: Int): ListIterator<String?> {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun subList(fromIndex: Int, toIndex: Int): List<String?> {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <E> Collection<E>.forceContains(x: Any?): Boolean = contains(x as E)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val strList = StrList()
|
||||||
|
|
||||||
|
if (strList.forceContains(1)) return "fail 1"
|
||||||
|
if (!strList.forceContains(null)) return "fail 2"
|
||||||
|
if (strList.forceContains("cde")) return "fail 3"
|
||||||
|
if (!strList.forceContains("abc")) return "fail 4"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+6
@@ -664,6 +664,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("strListContains.kt")
|
||||||
|
public void testStrListContains() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/strListContains.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("traitImplInheritsTraitImpl.kt")
|
@TestMetadata("traitImplInheritsTraitImpl.kt")
|
||||||
public void testTraitImplInheritsTraitImpl() throws Exception {
|
public void testTraitImplInheritsTraitImpl() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/traitImplInheritsTraitImpl.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/traitImplInheritsTraitImpl.kt");
|
||||||
|
|||||||
@@ -281,6 +281,12 @@ public class BridgeTestGenerated extends AbstractBridgeTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("strListContains.kt")
|
||||||
|
public void testStrListContains() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/strListContains.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("traitImplInheritsTraitImpl.kt")
|
@TestMetadata("traitImplInheritsTraitImpl.kt")
|
||||||
public void testTraitImplInheritsTraitImpl() throws Exception {
|
public void testTraitImplInheritsTraitImpl() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/traitImplInheritsTraitImpl.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/traitImplInheritsTraitImpl.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user