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;
|
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 com.google.common.collect.Sets;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
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 org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils.safeNameForLazyResolve;
|
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 DP declarationProvider;
|
||||||
protected final D thisDescriptor;
|
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 ConcurrentMap<Name, Set<FunctionDescriptor>> functionDescriptors;
|
||||||
private final Map<Name, ClassDescriptor> objectDescriptors = Maps.newHashMap();
|
private final ConcurrentMap<Name, Set<VariableDescriptor>> propertyDescriptors;
|
||||||
|
|
||||||
protected final Map<Name, Set<FunctionDescriptor>> functionDescriptors = Maps.newHashMap();
|
private final Collection<DeclarationDescriptor> allDescriptors;
|
||||||
private final Map<Name, Set<VariableDescriptor>> propertyDescriptors = Maps.newHashMap();
|
protected volatile boolean allDescriptorsComputed = false;
|
||||||
|
|
||||||
protected final List<DeclarationDescriptor> allDescriptors = Lists.newArrayList();
|
|
||||||
|
|
||||||
protected AbstractLazyMemberScope(
|
protected AbstractLazyMemberScope(
|
||||||
@NotNull ResolveSession resolveSession,
|
@NotNull ResolveSession resolveSession,
|
||||||
@@ -55,10 +53,17 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
|
|||||||
this.resolveSession = resolveSession;
|
this.resolveSession = resolveSession;
|
||||||
this.declarationProvider = declarationProvider;
|
this.declarationProvider = declarationProvider;
|
||||||
this.thisDescriptor = thisDescriptor;
|
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
|
@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);
|
ClassDescriptor known = cache.get(name);
|
||||||
if (known != null) return known;
|
if (known != null) return known;
|
||||||
|
|
||||||
@@ -77,9 +82,11 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
|
|||||||
ClassDescriptor classDescriptor = new LazyClassDescriptor(resolveSession, thisDescriptor, name,
|
ClassDescriptor classDescriptor = new LazyClassDescriptor(resolveSession, thisDescriptor, name,
|
||||||
JetClassInfoUtil.createClassLikeInfo(classOrObjectDeclaration));
|
JetClassInfoUtil.createClassLikeInfo(classOrObjectDeclaration));
|
||||||
|
|
||||||
cache.put(name, classDescriptor);
|
ClassDescriptor oldValue = cache.putIfAbsent(name, classDescriptor);
|
||||||
|
if (oldValue != null) return oldValue;
|
||||||
|
|
||||||
if (!object) {
|
if (!object) {
|
||||||
allDescriptors.add(classDescriptor);
|
registerDescriptor(classDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = classDescriptor;
|
result = classDescriptor;
|
||||||
@@ -123,8 +130,10 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
|
|||||||
getNonDeclaredFunctions(name, result);
|
getNonDeclaredFunctions(name, result);
|
||||||
|
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
functionDescriptors.put(name, result);
|
Set<FunctionDescriptor> oldValue = functionDescriptors.putIfAbsent(name, result);
|
||||||
allDescriptors.addAll(result);
|
if (oldValue != null) return oldValue;
|
||||||
|
|
||||||
|
registerDescriptors(result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -170,8 +179,10 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
|
|||||||
getNonDeclaredProperties(name, result);
|
getNonDeclaredProperties(name, result);
|
||||||
|
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
propertyDescriptors.put(name, result);
|
Set<VariableDescriptor> oldValue = propertyDescriptors.putIfAbsent(name, result);
|
||||||
allDescriptors.addAll(result);
|
if (oldValue != null) return oldValue;
|
||||||
|
|
||||||
|
registerDescriptors(result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -208,6 +219,16 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
|
|||||||
throw new UnsupportedOperationException(); // TODO
|
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
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<DeclarationDescriptor> getAllDescriptors() {
|
public Collection<DeclarationDescriptor> getAllDescriptors() {
|
||||||
|
|||||||
+15
-6
@@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve.lazy;
|
package org.jetbrains.jet.lang.resolve.lazy;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.intellij.openapi.util.Computable;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -64,8 +66,7 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
|
|||||||
Collection<T> extract(@NotNull JetType extractFrom, @NotNull Name name);
|
Collection<T> extract(@NotNull JetType extractFrom, @NotNull Name name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConstructorDescriptor primaryConstructor;
|
private final LazyValue<Optional<ConstructorDescriptor>> primaryConstructor;
|
||||||
private boolean primaryConstructorResolved = false;
|
|
||||||
|
|
||||||
public LazyClassMemberScope(
|
public LazyClassMemberScope(
|
||||||
@NotNull ResolveSession resolveSession,
|
@NotNull ResolveSession resolveSession,
|
||||||
@@ -73,6 +74,12 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
|
|||||||
@NotNull LazyClassDescriptor thisClass
|
@NotNull LazyClassDescriptor thisClass
|
||||||
) {
|
) {
|
||||||
super(resolveSession, declarationProvider, thisClass);
|
super(resolveSession, declarationProvider, thisClass);
|
||||||
|
this.primaryConstructor = resolveSession.getStorageManager().createLazyValue(new Computable<Optional<ConstructorDescriptor>>() {
|
||||||
|
@Override
|
||||||
|
public Optional<ConstructorDescriptor> compute() {
|
||||||
|
return Optional.fromNullable(resolvePrimaryConstructor());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -331,9 +338,12 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ConstructorDescriptor getPrimaryConstructor() {
|
public ConstructorDescriptor getPrimaryConstructor() {
|
||||||
if (primaryConstructorResolved) {
|
return primaryConstructor.get().orNull();
|
||||||
return primaryConstructor;
|
}
|
||||||
}
|
|
||||||
|
@Nullable
|
||||||
|
private ConstructorDescriptor resolvePrimaryConstructor() {
|
||||||
|
ConstructorDescriptor primaryConstructor = null;
|
||||||
if (GENERATE_CONSTRUCTORS_FOR.contains(thisDescriptor.getKind())) {
|
if (GENERATE_CONSTRUCTORS_FOR.contains(thisDescriptor.getKind())) {
|
||||||
JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
|
JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
|
||||||
if (!thisDescriptor.getKind().isObject()) {
|
if (!thisDescriptor.getKind().isObject()) {
|
||||||
@@ -353,7 +363,6 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
|
|||||||
primaryConstructor = constructor;
|
primaryConstructor = constructor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
primaryConstructorResolved = true;
|
|
||||||
return primaryConstructor;
|
return primaryConstructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-5
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve.lazy;
|
package org.jetbrains.jet.lang.resolve.lazy;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
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.name.Name;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
public class LazyPackageMemberScope extends AbstractLazyMemberScope<NamespaceDescriptor, PackageMemberDeclarationProvider> {
|
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,
|
public LazyPackageMemberScope(@NotNull ResolveSession resolveSession,
|
||||||
@NotNull PackageMemberDeclarationProvider declarationProvider,
|
@NotNull PackageMemberDeclarationProvider declarationProvider,
|
||||||
@NotNull NamespaceDescriptor thisPackage) {
|
@NotNull NamespaceDescriptor thisPackage) {
|
||||||
super(resolveSession, declarationProvider, thisPackage);
|
super(resolveSession, declarationProvider, thisPackage);
|
||||||
|
|
||||||
|
this.packageDescriptors = resolveSession.getStorageManager().createConcurrentMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NamespaceDescriptor getNamespace(@NotNull Name name) {
|
public NamespaceDescriptor getNamespace(@NotNull Name name) {
|
||||||
NamespaceDescriptor known = packageDescriptors.get(name);
|
NamespaceDescriptor known = packageDescriptors.get(name);
|
||||||
if (known != null) return known;
|
if (known != null) return known;
|
||||||
|
|
||||||
if (allDescriptorsComputed) return null;
|
if (allDescriptorsComputed) return null;
|
||||||
|
|
||||||
if (!declarationProvider.isPackageDeclared(name)) 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;
|
assert packageMemberDeclarationProvider != null : "Package is declared, but declaration provider is not found: " + name;
|
||||||
NamespaceDescriptor namespaceDescriptor = new LazyPackageDescriptor(thisDescriptor, name, resolveSession, packageMemberDeclarationProvider);
|
NamespaceDescriptor namespaceDescriptor = new LazyPackageDescriptor(thisDescriptor, name, resolveSession, packageMemberDeclarationProvider);
|
||||||
|
|
||||||
packageDescriptors.put(name, namespaceDescriptor);
|
NamespaceDescriptor oldValue = packageDescriptors.putIfAbsent(name, namespaceDescriptor);
|
||||||
allDescriptors.add(namespaceDescriptor);
|
if (oldValue != null) return oldValue;
|
||||||
|
|
||||||
|
registerDescriptor(namespaceDescriptor);
|
||||||
|
|
||||||
return namespaceDescriptor;
|
return namespaceDescriptor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
public class LockBasedStorageManager implements StorageManager {
|
public class LockBasedStorageManager implements StorageManager {
|
||||||
@@ -44,6 +45,11 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
return new ConcurrentHashMap<K, V>();
|
return new ConcurrentHashMap<K, V>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <E> Collection<E> createConcurrentCollection() {
|
||||||
|
return new ConcurrentLinkedQueue<E>();
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public <T> LazyValue<T> createLazyValue(@NotNull Computable<T> computable) {
|
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.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
public interface StorageManager {
|
public interface StorageManager {
|
||||||
@NotNull
|
@NotNull
|
||||||
<K, V> ConcurrentMap<K, V> createConcurrentMap();
|
<K, V> ConcurrentMap<K, V> createConcurrentMap();
|
||||||
|
|
||||||
|
<E> Collection<E> createConcurrentCollection();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
<T> LazyValue<T> createLazyValue(@NotNull Computable<T> computable);
|
<T> LazyValue<T> createLazyValue(@NotNull Computable<T> computable);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user