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.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils; 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.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument; import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument; import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
@@ -411,72 +410,78 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
private boolean isGenericToArrayPresent() { private boolean isGenericToArray(@NotNull FunctionDescriptor function) {
Collection<SimpleFunctionDescriptor> functions = if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) {
descriptor.getDefaultType().getMemberScope().getContributedFunctions(Name.identifier("toArray"), NoLookupLocation.FROM_BACKEND); return false;
for (FunctionDescriptor function : functions) { }
if (CallResolverUtilKt.isOrOverridesSynthesized(function)) {
continue;
}
if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) { KotlinType returnType = function.getReturnType();
continue; assert returnType != null : function.toString();
} KotlinType paramType = function.getValueParameters().get(0).getType();
if (KotlinBuiltIns.isArray(returnType) && KotlinBuiltIns.isArray(paramType)) {
KotlinType returnType = function.getReturnType(); KotlinType elementType = function.getTypeParameters().get(0).getDefaultType();
assert returnType != null : function.toString(); KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(descriptor);
KotlinType paramType = function.getValueParameters().get(0).getType(); if (KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(returnType))
if (KotlinBuiltIns.isArray(returnType) && KotlinBuiltIns.isArray(paramType)) { && KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(paramType))) {
KotlinType elementType = function.getTypeParameters().get(0).getDefaultType(); return true;
if (KotlinTypeChecker.DEFAULT.equalTypes(elementType, DescriptorUtilsKt.getBuiltIns(descriptor).getArrayElementType(returnType))
&& KotlinTypeChecker.DEFAULT.equalTypes(elementType, DescriptorUtilsKt
.getBuiltIns(descriptor).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() { private void generateToArray() {
if (descriptor.getKind() == ClassKind.INTERFACE) return;
KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(descriptor); KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(descriptor);
if (!isSubclass(descriptor, builtIns.getCollection())) return; if (!isSubclass(descriptor, builtIns.getCollection())) return;
int access = descriptor.getKind() == ClassKind.INTERFACE ? Collection<SimpleFunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getContributedFunctions(
ACC_PUBLIC | ACC_ABSTRACT : Name.identifier("toArray"), NoLookupLocation.FROM_BACKEND
ACC_PUBLIC; );
if (CodegenUtil.getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toArray"), builtIns.getArray()) == null) { boolean hasGenericToArray = false;
MethodVisitor mv = v.newMethod(NO_ORIGIN, access, "toArray", "()[Ljava/lang/Object;", null, null); boolean hasNonGenericToArray = false;
for (FunctionDescriptor function : functions) {
if (descriptor.getKind() != ClassKind.INTERFACE) { hasGenericToArray |= isGenericToArray(function);
InstructionAdapter iv = new InstructionAdapter(mv); hasNonGenericToArray |= isNonGenericToArray(function);
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);
}
} }
if (!isGenericToArrayPresent()) { if (!hasNonGenericToArray) {
MethodVisitor mv = v.newMethod(NO_ORIGIN, access, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", null, null); MethodVisitor mv = v.newMethod(NO_ORIGIN, ACC_PUBLIC, "toArray", "()[Ljava/lang/Object;", null, null);
if (descriptor.getKind() != ClassKind.INTERFACE) { InstructionAdapter iv = new InstructionAdapter(mv);
InstructionAdapter iv = new InstructionAdapter(mv); mv.visitCode();
mv.visitCode();
iv.load(0, classAsmType); 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;", false);
iv.areturn(Type.getType("[Ljava/lang/Object;"));
iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", FunctionCodegen.endVisit(mv, "toArray", myClass);
"(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;", false); }
iv.areturn(Type.getType("[Ljava/lang/Object;"));
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 inner class I1$DefaultImpls
public abstract method contains(p0: java.lang.Object): boolean 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 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 @kotlin.Metadata
@@ -138,6 +136,4 @@ public interface I2 {
inner class I2$DefaultImpls inner class I2$DefaultImpls
public abstract method contains(@org.jetbrains.annotations.NotNull p0: java.lang.String): boolean 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 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 remove (Lkotlin/text/MatchGroup;)Z
public abstract fun removeAll (Ljava/util/Collection;)Z public abstract fun removeAll (Ljava/util/Collection;)Z
public abstract fun retainAll (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 { public abstract interface class kotlin/text/MatchResult {