Simplify ImplementationBodyCodegen#generateToArray

- don't do anything for interfaces because there's no point in generating
  abstract methods which are already abstract in supertypes
- don't use getDeclaredFunctionByRawSignature, check function signature
  manually instead
- don't use isOrOverridesSynthesized because 'toArray' is never synthesized
This commit is contained in:
Alexander Udalov
2016-05-18 11:05:57 +03:00
parent b208995d73
commit 2200bfcc85
3 changed files with 56 additions and 57 deletions
@@ -49,7 +49,6 @@ import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
@@ -411,72 +410,78 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
private boolean isGenericToArrayPresent() {
Collection<SimpleFunctionDescriptor> functions =
descriptor.getDefaultType().getMemberScope().getContributedFunctions(Name.identifier("toArray"), NoLookupLocation.FROM_BACKEND);
for (FunctionDescriptor function : functions) {
if (CallResolverUtilKt.isOrOverridesSynthesized(function)) {
continue;
}
private boolean isGenericToArray(@NotNull FunctionDescriptor function) {
if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) {
return false;
}
if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) {
continue;
}
KotlinType returnType = function.getReturnType();
assert returnType != null : function.toString();
KotlinType paramType = function.getValueParameters().get(0).getType();
if (KotlinBuiltIns.isArray(returnType) && KotlinBuiltIns.isArray(paramType)) {
KotlinType elementType = function.getTypeParameters().get(0).getDefaultType();
if (KotlinTypeChecker.DEFAULT.equalTypes(elementType, DescriptorUtilsKt.getBuiltIns(descriptor).getArrayElementType(returnType))
&& KotlinTypeChecker.DEFAULT.equalTypes(elementType, DescriptorUtilsKt
.getBuiltIns(descriptor).getArrayElementType(paramType))) {
return true;
}
KotlinType returnType = function.getReturnType();
assert returnType != null : function.toString();
KotlinType paramType = function.getValueParameters().get(0).getType();
if (KotlinBuiltIns.isArray(returnType) && KotlinBuiltIns.isArray(paramType)) {
KotlinType elementType = function.getTypeParameters().get(0).getDefaultType();
KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(descriptor);
if (KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(returnType))
&& KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(paramType))) {
return true;
}
}
return false;
return false;
}
private static boolean isNonGenericToArray(@NotNull FunctionDescriptor function) {
if (!function.getValueParameters().isEmpty() || !function.getTypeParameters().isEmpty()) {
return false;
}
KotlinType returnType = function.getReturnType();
return returnType != null && KotlinBuiltIns.isArray(returnType);
}
private void generateToArray() {
if (descriptor.getKind() == ClassKind.INTERFACE) return;
KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(descriptor);
if (!isSubclass(descriptor, builtIns.getCollection())) return;
int access = descriptor.getKind() == ClassKind.INTERFACE ?
ACC_PUBLIC | ACC_ABSTRACT :
ACC_PUBLIC;
if (CodegenUtil.getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toArray"), builtIns.getArray()) == null) {
MethodVisitor mv = v.newMethod(NO_ORIGIN, access, "toArray", "()[Ljava/lang/Object;", null, null);
if (descriptor.getKind() != ClassKind.INTERFACE) {
InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitCode();
iv.load(0, classAsmType);
iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;", false);
iv.areturn(Type.getType("[Ljava/lang/Object;"));
FunctionCodegen.endVisit(mv, "toArray", myClass);
}
Collection<SimpleFunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getContributedFunctions(
Name.identifier("toArray"), NoLookupLocation.FROM_BACKEND
);
boolean hasGenericToArray = false;
boolean hasNonGenericToArray = false;
for (FunctionDescriptor function : functions) {
hasGenericToArray |= isGenericToArray(function);
hasNonGenericToArray |= isNonGenericToArray(function);
}
if (!isGenericToArrayPresent()) {
MethodVisitor mv = v.newMethod(NO_ORIGIN, access, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", null, null);
if (!hasNonGenericToArray) {
MethodVisitor mv = v.newMethod(NO_ORIGIN, ACC_PUBLIC, "toArray", "()[Ljava/lang/Object;", null, null);
if (descriptor.getKind() != ClassKind.INTERFACE) {
InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitCode();
iv.load(0, classAsmType);
iv.load(1, Type.getType("[Ljava/lang/Object;"));
iv.load(0, classAsmType);
iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;", false);
iv.areturn(Type.getType("[Ljava/lang/Object;"));
iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray",
"(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;", false);
iv.areturn(Type.getType("[Ljava/lang/Object;"));
FunctionCodegen.endVisit(mv, "toArray", myClass);
}
FunctionCodegen.endVisit(mv, "toArray", myClass);
}
if (!hasGenericToArray) {
MethodVisitor mv = v.newMethod(NO_ORIGIN, ACC_PUBLIC, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", null, null);
InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitCode();
iv.load(0, classAsmType);
iv.load(1, Type.getType("[Ljava/lang/Object;"));
iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray",
"(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;", false);
iv.areturn(Type.getType("[Ljava/lang/Object;"));
FunctionCodegen.endVisit(mv, "toArray", myClass);
}
}
@@ -122,8 +122,6 @@ public interface I1 {
inner class I1$DefaultImpls
public abstract method contains(p0: java.lang.Object): boolean
public abstract method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
public abstract method toArray(): java.lang.Object[]
public abstract method toArray(p0: java.lang.Object[]): java.lang.Object[]
}
@kotlin.Metadata
@@ -138,6 +136,4 @@ public interface I2 {
inner class I2$DefaultImpls
public abstract method contains(@org.jetbrains.annotations.NotNull p0: java.lang.String): boolean
public abstract method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
public abstract method toArray(): java.lang.Object[]
public abstract method toArray(p0: java.lang.Object[]): java.lang.Object[]
}
@@ -2089,8 +2089,6 @@ public abstract interface class kotlin/text/MatchGroupCollection : java/util/Col
public abstract fun remove (Lkotlin/text/MatchGroup;)Z
public abstract fun removeAll (Ljava/util/Collection;)Z
public abstract fun retainAll (Ljava/util/Collection;)Z
public abstract fun toArray ()[Ljava/lang/Object;
public abstract fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object;
}
public abstract interface class kotlin/text/MatchResult {