Lazy member scopes are now thread-safe.

NOTE: in this implementation there will be exceptions from rewrites on the trace.
This commit is contained in:
Andrey Breslav
2013-02-06 18:35:59 +04:00
parent 1cac7c1a41
commit 59b78e3628
5 changed files with 70 additions and 27 deletions
@@ -16,8 +16,6 @@
package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,6 +27,7 @@ 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 static org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils.safeNameForLazyResolve;
@@ -37,15 +36,14 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
protected final DP declarationProvider;
protected final D thisDescriptor;
protected boolean allDescriptorsComputed = false;
private final ConcurrentMap<Name, ClassDescriptor> classDescriptors;
private final ConcurrentMap<Name, ClassDescriptor> objectDescriptors;
private final Map<Name, ClassDescriptor> classDescriptors = Maps.newHashMap();
private final Map<Name, ClassDescriptor> objectDescriptors = Maps.newHashMap();
private final ConcurrentMap<Name, Set<FunctionDescriptor>> functionDescriptors;
private final ConcurrentMap<Name, Set<VariableDescriptor>> propertyDescriptors;
protected final Map<Name, Set<FunctionDescriptor>> functionDescriptors = Maps.newHashMap();
private final Map<Name, Set<VariableDescriptor>> propertyDescriptors = Maps.newHashMap();
protected final List<DeclarationDescriptor> allDescriptors = Lists.newArrayList();
private final Collection<DeclarationDescriptor> allDescriptors;
protected volatile boolean allDescriptorsComputed = false;
protected AbstractLazyMemberScope(
@NotNull ResolveSession resolveSession,
@@ -55,10 +53,17 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
this.resolveSession = resolveSession;
this.declarationProvider = declarationProvider;
this.thisDescriptor = thisDescriptor;
StorageManager storageManager = resolveSession.getStorageManager();
this.classDescriptors = storageManager.createConcurrentMap();
this.objectDescriptors = storageManager.createConcurrentMap();
this.functionDescriptors = storageManager.createConcurrentMap();
this.propertyDescriptors = storageManager.createConcurrentMap();
this.allDescriptors = storageManager.createConcurrentCollection();
}
@Nullable
private ClassDescriptor getClassOrObjectDescriptor(@NotNull Map<Name, ClassDescriptor> cache, @NotNull Name name, boolean object) {
private ClassDescriptor getClassOrObjectDescriptor(@NotNull ConcurrentMap<Name, ClassDescriptor> cache, @NotNull Name name, boolean object) {
ClassDescriptor known = cache.get(name);
if (known != null) return known;
@@ -77,9 +82,11 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
ClassDescriptor classDescriptor = new LazyClassDescriptor(resolveSession, thisDescriptor, name,
JetClassInfoUtil.createClassLikeInfo(classOrObjectDeclaration));
cache.put(name, classDescriptor);
ClassDescriptor oldValue = cache.putIfAbsent(name, classDescriptor);
if (oldValue != null) return oldValue;
if (!object) {
allDescriptors.add(classDescriptor);
registerDescriptor(classDescriptor);
}
result = classDescriptor;
@@ -123,8 +130,10 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
getNonDeclaredFunctions(name, result);
if (!result.isEmpty()) {
functionDescriptors.put(name, result);
allDescriptors.addAll(result);
Set<FunctionDescriptor> oldValue = functionDescriptors.putIfAbsent(name, result);
if (oldValue != null) return oldValue;
registerDescriptors(result);
}
return result;
}
@@ -170,8 +179,10 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
getNonDeclaredProperties(name, result);
if (!result.isEmpty()) {
propertyDescriptors.put(name, result);
allDescriptors.addAll(result);
Set<VariableDescriptor> oldValue = propertyDescriptors.putIfAbsent(name, result);
if (oldValue != null) return oldValue;
registerDescriptors(result);
}
return result;
}
@@ -208,6 +219,16 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
throw new UnsupportedOperationException(); // TODO
}
protected void registerDescriptor(@NotNull DeclarationDescriptor descriptor) {
assert !allDescriptorsComputed : "getAllDescriptors() has been called already";
allDescriptors.add(descriptor);
}
protected void registerDescriptors(@NotNull Collection<? extends DeclarationDescriptor> descriptors) {
assert !allDescriptorsComputed : "getAllDescriptors() has been called already";
allDescriptors.addAll(descriptors);
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
@@ -16,7 +16,9 @@
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;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -64,8 +66,7 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
Collection<T> extract(@NotNull JetType extractFrom, @NotNull Name name);
}
private ConstructorDescriptor primaryConstructor;
private boolean primaryConstructorResolved = false;
private final LazyValue<Optional<ConstructorDescriptor>> primaryConstructor;
public LazyClassMemberScope(
@NotNull ResolveSession resolveSession,
@@ -73,6 +74,12 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
@NotNull LazyClassDescriptor thisClass
) {
super(resolveSession, declarationProvider, thisClass);
this.primaryConstructor = resolveSession.getStorageManager().createLazyValue(new Computable<Optional<ConstructorDescriptor>>() {
@Override
public Optional<ConstructorDescriptor> compute() {
return Optional.fromNullable(resolvePrimaryConstructor());
}
});
}
@NotNull
@@ -331,9 +338,12 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
@Nullable
public ConstructorDescriptor getPrimaryConstructor() {
if (primaryConstructorResolved) {
return primaryConstructor;
}
return primaryConstructor.get().orNull();
}
@Nullable
private ConstructorDescriptor resolvePrimaryConstructor() {
ConstructorDescriptor primaryConstructor = null;
if (GENERATE_CONSTRUCTORS_FOR.contains(thisDescriptor.getKind())) {
JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
if (!thisDescriptor.getKind().isObject()) {
@@ -353,7 +363,6 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
primaryConstructor = constructor;
}
}
primaryConstructorResolved = true;
return primaryConstructor;
}
@@ -16,7 +16,6 @@
package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetDeclaration;
@@ -26,23 +25,26 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
public class LazyPackageMemberScope extends AbstractLazyMemberScope<NamespaceDescriptor, PackageMemberDeclarationProvider> {
private final Map<Name, NamespaceDescriptor> packageDescriptors = Maps.newHashMap();
private final ConcurrentMap<Name, NamespaceDescriptor> packageDescriptors;
public LazyPackageMemberScope(@NotNull ResolveSession resolveSession,
@NotNull PackageMemberDeclarationProvider declarationProvider,
@NotNull NamespaceDescriptor thisPackage) {
super(resolveSession, declarationProvider, thisPackage);
this.packageDescriptors = resolveSession.getStorageManager().createConcurrentMap();
}
@Override
public NamespaceDescriptor getNamespace(@NotNull Name name) {
NamespaceDescriptor known = packageDescriptors.get(name);
if (known != null) return known;
if (allDescriptorsComputed) return null;
if (!declarationProvider.isPackageDeclared(name)) return null;
@@ -52,8 +54,10 @@ 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);
packageDescriptors.put(name, namespaceDescriptor);
allDescriptors.add(namespaceDescriptor);
NamespaceDescriptor oldValue = packageDescriptors.putIfAbsent(name, namespaceDescriptor);
if (oldValue != null) return oldValue;
registerDescriptor(namespaceDescriptor);
return namespaceDescriptor;
}
@@ -27,6 +27,7 @@ import org.jetbrains.jet.util.slicedmap.WritableSlice;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
public class LockBasedStorageManager implements StorageManager {
@@ -44,6 +45,11 @@ public class LockBasedStorageManager implements StorageManager {
return new ConcurrentHashMap<K, V>();
}
@Override
public <E> Collection<E> createConcurrentCollection() {
return new ConcurrentLinkedQueue<E>();
}
@NotNull
@Override
public <T> LazyValue<T> createLazyValue(@NotNull Computable<T> computable) {
@@ -20,12 +20,15 @@ import com.intellij.openapi.util.Computable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import java.util.Collection;
import java.util.concurrent.ConcurrentMap;
public interface StorageManager {
@NotNull
<K, V> ConcurrentMap<K, V> createConcurrentMap();
<E> Collection<E> createConcurrentCollection();
@NotNull
<T> LazyValue<T> createLazyValue(@NotNull Computable<T> computable);