Perform computation of overridden descriptors lazy

It's makes sense in cases when descriptors are being substituted, because
in many cases their overridden are not needed.
This commit is contained in:
Denis Zharkov
2016-02-03 12:59:52 +03:00
parent fae6de9acd
commit 9e3d381eb3
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.descriptors.impl; package org.jetbrains.kotlin.descriptors.impl;
import kotlin.jvm.functions.Function0;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
@@ -48,6 +49,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
private boolean hasStableParameterNames = true; private boolean hasStableParameterNames = true;
private boolean hasSynthesizedParameterNames = false; private boolean hasSynthesizedParameterNames = false;
private Collection<? extends FunctionDescriptor> overriddenFunctions = null; private Collection<? extends FunctionDescriptor> overriddenFunctions = null;
private volatile Function0<Set<FunctionDescriptor>> lazyOverriddenFunctionsTask = null;
private final FunctionDescriptor original; private final FunctionDescriptor original;
private final Kind kind; private final Kind kind;
@Nullable @Nullable
@@ -162,9 +164,22 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
@NotNull @NotNull
@Override @Override
public Collection<? extends FunctionDescriptor> getOverriddenDescriptors() { public Collection<? extends FunctionDescriptor> getOverriddenDescriptors() {
performOverriddenLazyCalculationIfNeeded();
return overriddenFunctions != null ? overriddenFunctions : Collections.<FunctionDescriptor>emptyList(); return overriddenFunctions != null ? overriddenFunctions : Collections.<FunctionDescriptor>emptyList();
} }
private void performOverriddenLazyCalculationIfNeeded() {
Function0<Set<FunctionDescriptor>> overriddenTask = lazyOverriddenFunctionsTask;
if (overriddenTask != null) {
overriddenFunctions = overriddenTask.invoke();
// Here it's important that this assignment is strictly after previous one
// `lazyOverriddenFunctionsTask` is volatile, so when someone will see that it's null,
// he can read consistent collection from `overriddenFunctions`,
// because it's assignment happens-before of "lazyOverriddenFunctionsTask = null"
lazyOverriddenFunctionsTask = null;
}
}
@NotNull @NotNull
@Override @Override
public Modality getModality() { public Modality getModality() {
@@ -443,7 +458,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
configuration.preserveSourceElement); configuration.preserveSourceElement);
List<TypeParameterDescriptor> substitutedTypeParameters; List<TypeParameterDescriptor> substitutedTypeParameters;
TypeSubstitutor substitutor; final TypeSubstitutor substitutor;
if (configuration.newTypeParameters == null) { if (configuration.newTypeParameters == null) {
List<TypeParameterDescriptor> originalTypeParameters = getTypeParameters(); List<TypeParameterDescriptor> originalTypeParameters = getTypeParameters();
@@ -520,16 +535,27 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
substitutedDescriptor.setInitialSignatureDescriptor(initialSignatureSubstituted); substitutedDescriptor.setInitialSignatureDescriptor(initialSignatureSubstituted);
} }
if (configuration.copyOverrides && !getOverriddenDescriptors().isEmpty()) { if (configuration.copyOverrides && !getOriginal().getOverriddenDescriptors().isEmpty()) {
if (configuration.originalSubstitutor.isEmpty()) { if (configuration.originalSubstitutor.isEmpty()) {
substitutedDescriptor.setOverriddenDescriptors(getOverriddenDescriptors()); Function0<Set<FunctionDescriptor>> overriddenFunctionsTask = lazyOverriddenFunctionsTask;
if (overriddenFunctionsTask != null) {
substitutedDescriptor.lazyOverriddenFunctionsTask = overriddenFunctionsTask;
}
else {
substitutedDescriptor.setOverriddenDescriptors(getOverriddenDescriptors());
}
} }
else { else {
Collection<CallableMemberDescriptor> substitutedOverridden = SmartSet.create(); substitutedDescriptor.lazyOverriddenFunctionsTask = new Function0<Set<FunctionDescriptor>>() {
for (FunctionDescriptor overriddenFunction : getOverriddenDescriptors()) { @Override
substitutedOverridden.add(overriddenFunction.substitute(substitutor)); public Set<FunctionDescriptor> invoke() {
} SmartSet<FunctionDescriptor> result = SmartSet.create();
substitutedDescriptor.setOverriddenDescriptors(substitutedOverridden); for (FunctionDescriptor overriddenFunction : getOverriddenDescriptors()) {
result.add(overriddenFunction.substitute(substitutor));
}
return result;
}
};
} }
} }