Migrating to memoized functions and nullable lazy values

This commit is contained in:
Andrey Breslav
2013-02-08 16:36:40 +04:00
parent 7ddadd9a6c
commit ccbd4018b1
5 changed files with 87 additions and 81 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.collect.Sets;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
@@ -26,21 +27,24 @@ import org.jetbrains.jet.lang.resolve.name.LabelName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils.safeNameForLazyResolve;
import static org.jetbrains.jet.lang.resolve.lazy.StorageManager.MemoizationMode.STRONG;
public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, DP extends DeclarationProvider> implements JetScope {
protected final ResolveSession resolveSession;
protected final DP declarationProvider;
protected final D thisDescriptor;
private final ConcurrentMap<Name, ClassDescriptor> classDescriptors;
private final ConcurrentMap<Name, ClassDescriptor> objectDescriptors;
private final Function<Name, ClassDescriptor> classDescriptors;
private final Function<Name, ClassDescriptor> objectDescriptors;
private final ConcurrentMap<Name, Set<FunctionDescriptor>> functionDescriptors;
private final ConcurrentMap<Name, Set<VariableDescriptor>> propertyDescriptors;
private final Function<Name, Set<FunctionDescriptor>> functionDescriptors;
private final Function<Name, Set<VariableDescriptor>> propertyDescriptors;
private final Collection<DeclarationDescriptor> allDescriptors;
protected volatile boolean allDescriptorsComputed = false;
@@ -55,25 +59,40 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
this.thisDescriptor = thisDescriptor;
StorageManager storageManager = resolveSession.getStorageManager();
this.classDescriptors = storageManager.createConcurrentMap();
this.objectDescriptors = storageManager.createConcurrentMap();
this.functionDescriptors = storageManager.createConcurrentMap();
this.propertyDescriptors = storageManager.createConcurrentMap();
this.classDescriptors = storageManager.createMemoizedFunctionWithNullableValues(new Function<Name, ClassDescriptor>() {
@Override
public ClassDescriptor fun(Name name) {
return resolveClassOrObjectDescriptor(name, false);
}
}, STRONG);
this.objectDescriptors = storageManager.createMemoizedFunctionWithNullableValues(new Function<Name, ClassDescriptor>() {
@Override
public ClassDescriptor fun(Name name) {
return resolveClassOrObjectDescriptor(name, true);
}
}, STRONG);
this.functionDescriptors = storageManager.createMemoizedFunction(new Function<Name, Set<FunctionDescriptor>>() {
@Override
public Set<FunctionDescriptor> fun(Name name) {
return doGetFunctions(name);
}
}, STRONG);
this.propertyDescriptors = storageManager.createMemoizedFunction(new Function<Name, Set<VariableDescriptor>>() {
@Override
public Set<VariableDescriptor> fun(Name name) {
return doGetProperties(name);
}
}, STRONG);
this.allDescriptors = storageManager.createConcurrentCollection();
}
@Nullable
private ClassDescriptor getClassOrObjectDescriptor(@NotNull ConcurrentMap<Name, ClassDescriptor> cache, @NotNull Name name, boolean object) {
ClassDescriptor known = cache.get(name);
if (known != null) return known;
if (allDescriptorsComputed) return null;
private ClassDescriptor resolveClassOrObjectDescriptor(@NotNull Name name, boolean object) {
Collection<JetClassOrObject> classOrObjectDeclarations = declarationProvider.getClassOrObjectDeclarations(name);
if (classOrObjectDeclarations.isEmpty()) return null;
ClassDescriptor result = null;
for (JetClassOrObject classOrObjectDeclaration : classOrObjectDeclarations) {
// TODO: when enum entries with constructors are dropped, replace with declaresObjectOrEnumConstant()
@@ -82,16 +101,13 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
ClassDescriptor classDescriptor = new LazyClassDescriptor(resolveSession, thisDescriptor, name,
JetClassInfoUtil.createClassLikeInfo(classOrObjectDeclaration));
ClassDescriptor oldValue = cache.putIfAbsent(name, classDescriptor);
if (oldValue != null) return oldValue;
if (!object) {
registerDescriptor(classDescriptor);
}
result = classDescriptor;
return classDescriptor;
}
return result;
return null;
}
private static boolean declaresObjectOrEnumConstant(JetClassOrObject declaration) {
@@ -100,23 +116,22 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
@Override
public ClassifierDescriptor getClassifier(@NotNull Name name) {
return getClassOrObjectDescriptor(classDescriptors, name, false);
return classDescriptors.fun(name);
}
@Override
public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
return getClassOrObjectDescriptor(objectDescriptors, name, true);
return objectDescriptors.fun(name);
}
@NotNull
@Override
public Set<FunctionDescriptor> getFunctions(@NotNull Name name) {
Set<FunctionDescriptor> known = functionDescriptors.get(name);
if (known != null) return known;
// If all descriptors are already computed, we are
if (allDescriptorsComputed) return Collections.emptySet();
return functionDescriptors.fun(name);
}
@NotNull
private Set<FunctionDescriptor> doGetFunctions(@NotNull Name name) {
Set<FunctionDescriptor> result = Sets.newLinkedHashSet();
Collection<JetNamedFunction> declarations = declarationProvider.getFunctionDeclarations(name);
@@ -130,9 +145,6 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
getNonDeclaredFunctions(name, result);
if (!result.isEmpty()) {
Set<FunctionDescriptor> oldValue = functionDescriptors.putIfAbsent(name, result);
if (oldValue != null) return oldValue;
registerDescriptors(result);
}
return result;
@@ -146,12 +158,11 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
@NotNull
@Override
public Set<VariableDescriptor> getProperties(@NotNull Name name) {
Set<VariableDescriptor> known = propertyDescriptors.get(name);
if (known != null) return known;
// If all descriptors are already computed, we are
if (allDescriptorsComputed) return Collections.emptySet();
return propertyDescriptors.fun(name);
}
@NotNull
public Set<VariableDescriptor> doGetProperties(@NotNull Name name) {
Set<VariableDescriptor> result = Sets.newLinkedHashSet();
Collection<JetProperty> declarations = declarationProvider.getPropertyDeclarations(name);
@@ -178,12 +189,8 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
getNonDeclaredProperties(name, result);
if (!result.isEmpty()) {
Set<VariableDescriptor> oldValue = propertyDescriptors.putIfAbsent(name, result);
if (oldValue != null) return oldValue;
registerDescriptors(result);
registerDescriptors(result);
}
return result;
}
@@ -23,7 +23,9 @@ import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.Computable;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespaceHeader;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
@@ -31,7 +33,6 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
public class FileBasedDeclarationProviderFactory implements DeclarationProviderFactory {
@@ -45,7 +46,7 @@ public class FileBasedDeclarationProviderFactory implements DeclarationProviderF
private final StorageManager storageManager;
private final LazyValue<Index> index;
private final ConcurrentMap<FqName, PackageMemberDeclarationProvider> packageDeclarationProviders;
private final Function<FqName, PackageMemberDeclarationProvider> packageDeclarationProviders;
public FileBasedDeclarationProviderFactory(@NotNull StorageManager storageManager, @NotNull Collection<JetFile> files) {
this(storageManager, files, Predicates.<FqName>alwaysFalse());
@@ -64,7 +65,12 @@ public class FileBasedDeclarationProviderFactory implements DeclarationProviderF
return computeFilesByPackage(files);
}
});
this.packageDeclarationProviders = storageManager.createConcurrentMap();
this.packageDeclarationProviders = storageManager.createMemoizedFunctionWithNullableValues(new Function<FqName, PackageMemberDeclarationProvider>() {
@Override
public PackageMemberDeclarationProvider fun(FqName fqName) {
return createPackageMemberDeclarationProvider(fqName);
}
}, StorageManager.MemoizationMode.STRONG);
}
@NotNull
@@ -109,11 +115,11 @@ public class FileBasedDeclarationProviderFactory implements DeclarationProviderF
@Override
public PackageMemberDeclarationProvider getPackageMemberDeclarationProvider(@NotNull FqName packageFqName) {
PackageMemberDeclarationProvider cached = packageDeclarationProviders.get(packageFqName);
if (cached != null) {
return cached;
}
return packageDeclarationProviders.fun(packageFqName);
}
@Nullable
public PackageMemberDeclarationProvider createPackageMemberDeclarationProvider(@NotNull FqName packageFqName) {
if (!isPackageDeclaredExplicitly(packageFqName)) {
if (isPackageDeclaredExternally.apply(packageFqName)) {
return EmptyPackageMemberDeclarationProvider.INSTANCE;
@@ -121,15 +127,7 @@ public class FileBasedDeclarationProviderFactory implements DeclarationProviderF
return null;
}
FileBasedPackageMemberDeclarationProvider provider =
new FileBasedPackageMemberDeclarationProvider(storageManager, packageFqName, this, index.get().filesByPackage.get(packageFqName));
PackageMemberDeclarationProvider oldValue = packageDeclarationProviders.putIfAbsent(packageFqName, provider);
if (oldValue != null) {
return oldValue;
}
return provider;
return new FileBasedPackageMemberDeclarationProvider(storageManager, packageFqName, this, index.get().filesByPackage.get(packageFqName));
}
@NotNull
@@ -16,7 +16,6 @@
package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
@@ -71,7 +70,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
private final LazyValue<ReceiverParameterDescriptor> thisAsReceiverParameter;
private final LazyValue<List<AnnotationDescriptor>> annotations;
private final LazyValue<Optional<ClassDescriptor>> classObjectDescriptor;
private final LazyValue<ClassDescriptor> classObjectDescriptor;
private final LazyClassMemberScope unsubstitutedMemberScope;
private final JetScope unsubstitutedInnerClassesScope;
@@ -129,10 +128,10 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
return resolveAnnotations();
}
});
this.classObjectDescriptor = storageManager.createLazyValue(new Computable<Optional<ClassDescriptor>>() {
this.classObjectDescriptor = storageManager.createNullableLazyValue(new Computable<ClassDescriptor>() {
@Override
public Optional<ClassDescriptor> compute() {
return Optional.fromNullable(computeClassObjectDescriptor());
public ClassDescriptor compute() {
return computeClassObjectDescriptor();
}
});
this.scopeForClassHeaderResolution = storageManager.createLazyValue(new Computable<JetScope>() {
@@ -273,7 +272,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
@Override
public ClassDescriptor getClassObjectDescriptor() {
return classObjectDescriptor.get().orNull();
return classObjectDescriptor.get();
}
@Nullable
@@ -16,7 +16,6 @@
package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiElement;
@@ -66,7 +65,7 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
Collection<T> extract(@NotNull JetType extractFrom, @NotNull Name name);
}
private final LazyValue<Optional<ConstructorDescriptor>> primaryConstructor;
private final LazyValue<ConstructorDescriptor> primaryConstructor;
public LazyClassMemberScope(
@NotNull ResolveSession resolveSession,
@@ -74,10 +73,10 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
@NotNull LazyClassDescriptor thisClass
) {
super(resolveSession, declarationProvider, thisClass);
this.primaryConstructor = resolveSession.getStorageManager().createLazyValue(new Computable<Optional<ConstructorDescriptor>>() {
this.primaryConstructor = resolveSession.getStorageManager().createNullableLazyValue(new Computable<ConstructorDescriptor>() {
@Override
public Optional<ConstructorDescriptor> compute() {
return Optional.fromNullable(resolvePrimaryConstructor());
public ConstructorDescriptor compute() {
return resolvePrimaryConstructor();
}
});
}
@@ -338,7 +337,7 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
@Nullable
public ConstructorDescriptor getPrimaryConstructor() {
return primaryConstructor.get().orNull();
return primaryConstructor.get();
}
@Nullable
@@ -16,7 +16,9 @@
package org.jetbrains.jet.lang.resolve.lazy;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetFile;
@@ -26,27 +28,31 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
public class LazyPackageMemberScope extends AbstractLazyMemberScope<NamespaceDescriptor, PackageMemberDeclarationProvider> {
private final ConcurrentMap<Name, NamespaceDescriptor> packageDescriptors;
private final Function<Name, NamespaceDescriptor> packageDescriptors;
public LazyPackageMemberScope(@NotNull ResolveSession resolveSession,
@NotNull PackageMemberDeclarationProvider declarationProvider,
@NotNull NamespaceDescriptor thisPackage) {
super(resolveSession, declarationProvider, thisPackage);
this.packageDescriptors = resolveSession.getStorageManager().createConcurrentMap();
this.packageDescriptors = resolveSession.getStorageManager().createMemoizedFunctionWithNullableValues(new Function<Name, NamespaceDescriptor>() {
@Override
public NamespaceDescriptor fun(Name name) {
return createPackageDescriptor(name);
}
}, StorageManager.MemoizationMode.STRONG);
}
@Override
public NamespaceDescriptor getNamespace(@NotNull Name name) {
NamespaceDescriptor known = packageDescriptors.get(name);
if (known != null) return known;
if (allDescriptorsComputed) return null;
return packageDescriptors.fun(name);
}
@Nullable
public NamespaceDescriptor createPackageDescriptor(@NotNull Name name) {
if (!declarationProvider.isPackageDeclared(name)) return null;
PackageMemberDeclarationProvider packageMemberDeclarationProvider = resolveSession.getDeclarationProviderFactory().getPackageMemberDeclarationProvider(
@@ -54,9 +60,6 @@ public class LazyPackageMemberScope extends AbstractLazyMemberScope<NamespaceDes
assert packageMemberDeclarationProvider != null : "Package is declared, but declaration provider is not found: " + name;
NamespaceDescriptor namespaceDescriptor = new LazyPackageDescriptor(thisDescriptor, name, resolveSession, packageMemberDeclarationProvider);
NamespaceDescriptor oldValue = packageDescriptors.putIfAbsent(name, namespaceDescriptor);
if (oldValue != null) return oldValue;
registerDescriptor(namespaceDescriptor);
return namespaceDescriptor;