Generate special bridges for builtins with same name but different JVM descriptor

This commit is contained in:
Denis Zharkov
2015-10-15 21:00:49 +03:00
parent 07d8754adb
commit d335f71dfe
5 changed files with 52 additions and 7 deletions
@@ -516,7 +516,7 @@ public class FunctionCodegen {
// If the function doesn't have a physical declaration among super-functions, it's a SAM adapter or alike and doesn't need bridges // If the function doesn't have a physical declaration among super-functions, it's a SAM adapter or alike and doesn't need bridges
if (CallResolverUtilKt.isOrOverridesSynthesized(descriptor)) return; if (CallResolverUtilKt.isOrOverridesSynthesized(descriptor)) return;
boolean isSpecial = SpecialBuiltinMembers.doesOverrideBuiltinWithDifferentJvmName(descriptor); boolean isSpecial = SpecialBuiltinMembers.getOverriddenBuiltinWithDifferentJvmDescriptor(descriptor) != null;
Set<Bridge<Method>> bridgesToGenerate; Set<Bridge<Method>> bridgesToGenerate;
if (!isSpecial) { if (!isSpecial) {
@@ -560,7 +560,7 @@ public class FunctionCodegen {
} }
if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) { if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) {
CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinWithDifferentJvmName(descriptor); CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinWithDifferentJvmDescriptor(descriptor);
assert overridden != null; assert overridden != null;
Method method = typeMapper.mapSignature(descriptor).getAsmMethod(); Method method = typeMapper.mapSignature(descriptor).getAsmMethod();
@@ -852,6 +852,8 @@ public class FunctionCodegen {
assert descriptor.getValueParameters().size() == 1 : "Should be descriptor with one value parameter, but found: " + descriptor; assert descriptor.getValueParameters().size() == 1 : "Should be descriptor with one value parameter, but found: " + descriptor;
if (bridge.getArgumentTypes()[0].getSort() != Type.OBJECT) return;
iv.load(1, OBJECT_TYPE); iv.load(1, OBJECT_TYPE);
JetType jetType = descriptor.getValueParameters().get(0).getType(); JetType jetType = descriptor.getValueParameters().get(0).getType();
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.backend.common.bridges.* import org.jetbrains.kotlin.backend.common.bridges.*
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.java.getOverriddenBuiltinWithDifferentJvmName
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.getOverriddenBuiltinWithDifferentJvmDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
@@ -41,16 +41,18 @@ object BuiltinSpecialBridgesUtil {
val functionHandle = DescriptorBasedFunctionHandle(function) val functionHandle = DescriptorBasedFunctionHandle(function)
val fake = !functionHandle.isDeclaration val fake = !functionHandle.isDeclaration
val overriddenBuiltin = function.getOverriddenBuiltinWithDifferentJvmName()!! val overriddenBuiltin = function.getOverriddenBuiltinWithDifferentJvmDescriptor()!!
val reachableDeclarations = findAllReachableDeclarations(function) val reachableDeclarations = findAllReachableDeclarations(function)
val needGenerateSpecialBridge = needGenerateSpecialBridge(function, reachableDeclarations, overriddenBuiltin)
// e.g. `getSize()I` // e.g. `getSize()I`
val methodItself = signatureByDescriptor(function) val methodItself = signatureByDescriptor(function)
// e.g. `size()I` // e.g. `size()I`
val overriddenBuiltinSignature = signatureByDescriptor(overriddenBuiltin) val overriddenBuiltinSignature = signatureByDescriptor(overriddenBuiltin)
val needGenerateSpecialBridge = needGenerateSpecialBridge(function, reachableDeclarations, overriddenBuiltin)
&& methodItself != overriddenBuiltinSignature
val specialBridge = if (needGenerateSpecialBridge) val specialBridge = if (needGenerateSpecialBridge)
BridgeForBuiltinSpecial(overriddenBuiltinSignature, methodItself, isSpecial = true) BridgeForBuiltinSpecial(overriddenBuiltinSignature, methodItself, isSpecial = true)
else null else null
@@ -3,6 +3,7 @@
public method contains(p0: java.lang.Object): boolean public method contains(p0: java.lang.Object): boolean
public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
public abstract method getSize(): int public abstract method getSize(): int
public abstract method remove(p0: java.lang.Object): boolean
public final method size(): int public final method size(): int
public method toArray(): java.lang.Object[] public method toArray(): java.lang.Object[]
public method toArray(p0: java.lang.Object[]): java.lang.Object[] public method toArray(p0: java.lang.Object[]): java.lang.Object[]
@@ -14,6 +15,8 @@
public final method contains(p0: java.lang.Object): boolean public final method contains(p0: java.lang.Object): boolean
public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
public abstract method getSize(): int public abstract method getSize(): int
public final method remove(p0: java.lang.Object): boolean
public abstract method remove(p0: java.lang.String): boolean
public final method size(): int public final method size(): int
public method toArray(): java.lang.Object[] public method toArray(): java.lang.Object[]
public method toArray(p0: java.lang.Object[]): java.lang.Object[] public method toArray(p0: java.lang.Object[]): java.lang.Object[]
@@ -21,8 +24,12 @@
@kotlin.jvm.internal.KotlinClass A3 { @kotlin.jvm.internal.KotlinClass A3 {
public method <init>(): void public method <init>(): void
public synthetic method contains(p0: java.lang.Object): boolean
public abstract method getSize(): int public abstract method getSize(): int
public synthetic method indexOf(p0: java.lang.Object): int
public synthetic method lastIndexOf(p0: java.lang.Object): int
public final method remove(p0: int): java.lang.Object public final method remove(p0: int): java.lang.Object
public synthetic method remove(p0: java.lang.Object): boolean
public synthetic method removeAt(p0: int): java.lang.Object public synthetic method removeAt(p0: int): java.lang.Object
public final method size(): int public final method size(): int
} }
@@ -32,15 +39,26 @@
public method contains(p0: java.lang.Object): boolean public method contains(p0: java.lang.Object): boolean
public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
public abstract method getSize(): int public abstract method getSize(): int
public synthetic method indexOf(p0: java.lang.Object): int
public synthetic method lastIndexOf(p0: java.lang.Object): int
public final method remove(p0: int): java.lang.Object public final method remove(p0: int): java.lang.Object
public synthetic method remove(p0: java.lang.Object): boolean
public synthetic method removeAt(p0: int): java.lang.Object public synthetic method removeAt(p0: int): java.lang.Object
public final method size(): int public final method size(): int
} }
@kotlin.jvm.internal.KotlinClass A5 { @kotlin.jvm.internal.KotlinClass A5 {
public method <init>(): void public method <init>(): void
public final method contains(p0: java.lang.Object): boolean
public synthetic method contains(p0: java.lang.String): boolean
public abstract method getSize(): int public abstract method getSize(): int
public final method indexOf(p0: java.lang.Object): int
public synthetic method indexOf(p0: java.lang.String): int
public final method lastIndexOf(p0: java.lang.Object): int
public synthetic method lastIndexOf(p0: java.lang.String): int
public final method remove(p0: int): java.lang.String public final method remove(p0: int): java.lang.String
public final method remove(p0: java.lang.Object): boolean
public synthetic method remove(p0: java.lang.String): boolean
public synthetic method removeAt(p0: int): java.lang.String public synthetic method removeAt(p0: int): java.lang.String
public final method size(): int public final method size(): int
} }
@@ -51,7 +69,13 @@
public final method contains(p0: java.lang.Object): boolean public final method contains(p0: java.lang.Object): boolean
public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
public abstract method getSize(): int public abstract method getSize(): int
public final method indexOf(p0: java.lang.Object): int
public synthetic method indexOf(p0: java.lang.String): int
public final method lastIndexOf(p0: java.lang.Object): int
public synthetic method lastIndexOf(p0: java.lang.String): int
public final method remove(p0: int): java.lang.String public final method remove(p0: int): java.lang.String
public final method remove(p0: java.lang.Object): boolean
public synthetic method remove(p0: java.lang.String): boolean
public synthetic method removeAt(p0: int): java.lang.String public synthetic method removeAt(p0: int): java.lang.String
public final method size(): int public final method size(): int
} }
@@ -61,6 +85,8 @@
public method contains(p0: int): boolean public method contains(p0: int): boolean
public final method contains(p0: java.lang.Object): boolean public final method contains(p0: java.lang.Object): boolean
public abstract method getSize(): int public abstract method getSize(): int
public abstract method remove(p0: java.lang.Integer): boolean
public final method remove(p0: java.lang.Object): boolean
public final method size(): int public final method size(): int
public method toArray(): java.lang.Object[] public method toArray(): java.lang.Object[]
public method toArray(p0: java.lang.Object[]): java.lang.Object[] public method toArray(p0: java.lang.Object[]): java.lang.Object[]
@@ -70,6 +96,7 @@
public method <init>(): void public method <init>(): void
public method contains(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean public method contains(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
public abstract method getSize(): int public abstract method getSize(): int
public abstract method remove(p0: java.lang.Object): boolean
public final method size(): int public final method size(): int
public method toArray(): java.lang.Object[] public method toArray(): java.lang.Object[]
public method toArray(p0: java.lang.Object[]): java.lang.Object[] public method toArray(p0: java.lang.Object[]): java.lang.Object[]
@@ -101,7 +101,7 @@ fun foo(
// 0 signature \(TW;\)Z // 0 signature \(TW;\)Z
// 0 signature \(TR;\)Z // 0 signature \(TR;\)Z
// 6 signature \(Ljava/util/Collection<\+Ljava/lang/Object;>;\)Z // 6 signature \(Ljava/util/Collection<\+Ljava/lang/Object;>;\)Z
// 3 public final bridge contains\(Ljava/lang/Object;\)Z // 4 public final bridge contains\(Ljava/lang/Object;\)Z
// 4 INVOKEVIRTUAL A[0-9]\.contains \(Ljava/lang/String;\)Z // 4 INVOKEVIRTUAL A[0-9]\.contains \(Ljava/lang/String;\)Z
// 4 INVOKEVIRTUAL A[0-9]\.contains \(Ljava/lang/Object;\)Z // 4 INVOKEVIRTUAL A[0-9]\.contains \(Ljava/lang/Object;\)Z
// 2 INVOKEVIRTUAL A7\.contains \(I\)Z // 2 INVOKEVIRTUAL A7\.contains \(I\)Z
@@ -29,6 +29,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.addToStdlib.check import org.jetbrains.kotlin.utils.addToStdlib.check
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties.getBuiltinSpecialPropertyGetterName import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties.getBuiltinSpecialPropertyGetterName
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.sameAsBuiltinMethodWithErasedValueParameters
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
object BuiltinSpecialProperties { object BuiltinSpecialProperties {
@@ -47,7 +49,7 @@ object BuiltinSpecialProperties {
PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.getInversedShortNamesMap() PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.getInversedShortNamesMap()
private val FQ_NAMES = PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.keySet() private val FQ_NAMES = PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.keySet()
private val SHORT_NAMES = FQ_NAMES.map { it.shortName() }.toSet() internal val SHORT_NAMES = FQ_NAMES.map { it.shortName() }.toSet()
fun hasBuiltinSpecialPropertyFqName(callableMemberDescriptor: CallableMemberDescriptor): Boolean { fun hasBuiltinSpecialPropertyFqName(callableMemberDescriptor: CallableMemberDescriptor): Boolean {
if (callableMemberDescriptor.name !in SHORT_NAMES) return false if (callableMemberDescriptor.name !in SHORT_NAMES) return false
@@ -183,6 +185,18 @@ fun <T : CallableMemberDescriptor> T.getOverriddenBuiltinWithDifferentJvmName():
fun CallableMemberDescriptor.doesOverrideBuiltinWithDifferentJvmName(): Boolean = getOverriddenBuiltinWithDifferentJvmName() != null fun CallableMemberDescriptor.doesOverrideBuiltinWithDifferentJvmName(): Boolean = getOverriddenBuiltinWithDifferentJvmName() != null
@Suppress("UNCHECKED_CAST")
fun <T : CallableMemberDescriptor> T.getOverriddenBuiltinWithDifferentJvmDescriptor(): T? {
getOverriddenBuiltinWithDifferentJvmName()?.let { return it }
if (!name.sameAsBuiltinMethodWithErasedValueParameters) return null
return firstOverridden {
it.isFromBuiltins()
&& it.getSpecialSignatureInfo() == BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo.GENERIC_PARAMETER
}?.original as T?
}
fun getJvmMethodNameIfSpecial(callableMemberDescriptor: CallableMemberDescriptor): String? { fun getJvmMethodNameIfSpecial(callableMemberDescriptor: CallableMemberDescriptor): String? {
val builtinOverridden = getBuiltinOverriddenThatAffectsJvmName(callableMemberDescriptor)?.propertyIfAccessor val builtinOverridden = getBuiltinOverriddenThatAffectsJvmName(callableMemberDescriptor)?.propertyIfAccessor
?: return null ?: return null