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:
+37
-16
@@ -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() {
|
||||
|
||||
+15
-6
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+9
-5
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user