From 8a240e82bda60b4d77017bfd82bf8c788a2d31ba Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 8 Feb 2013 13:22:22 +0400 Subject: [PATCH] Thread-safe lazy values introduced into LazyClassDescriptor --- .../resolve/lazy/LazyClassDescriptor.java | 258 +++++++++++------- 1 file changed, 158 insertions(+), 100 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java index 1ba80c895f1..c4eafce035f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java @@ -16,17 +16,22 @@ 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; 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; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.AnnotationResolver; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.DescriptorResolver; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.lazy.data.FilteringClassLikeInfo; import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil; import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo; @@ -64,17 +69,16 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc private final ClassKind kind; private final boolean isInner; - private ReceiverParameterDescriptor thisAsReceiverParameter; - private List annotations; - private ClassDescriptor classObjectDescriptor; - private boolean classObjectDescriptorResolved = false; + private final LazyValue thisAsReceiverParameter; + private final LazyValue> annotations; + private final LazyValue> classObjectDescriptor; private final LazyClassMemberScope unsubstitutedMemberScope; private final JetScope unsubstitutedInnerClassesScope; - private JetScope scopeForClassHeaderResolution; - private JetScope scopeForMemberDeclarationResolution; - private JetScope scopeForPropertyInitializerResolution; + private final LazyValue scopeForClassHeaderResolution; + private final LazyValue scopeForMemberDeclarationResolution; + private final LazyValue scopeForPropertyInitializerResolution; public LazyClassDescriptor( @@ -111,6 +115,44 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc } this.visibility = resolveVisibilityFromModifiers(modifierList, getDefaultClassVisibility(this)); this.isInner = isInnerClass(modifierList); + + StorageManager storageManager = resolveSession.getStorageManager(); + this.thisAsReceiverParameter = storageManager.createLazyValue(new Computable() { + @Override + public ReceiverParameterDescriptor compute() { + return DescriptorResolver.createLazyReceiverParameterDescriptor(LazyClassDescriptor.this); + } + }); + this.annotations = storageManager.createLazyValue(new Computable>() { + @Override + public List compute() { + return resolveAnnotations(); + } + }); + this.classObjectDescriptor = storageManager.createLazyValue(new Computable>() { + @Override + public Optional compute() { + return Optional.fromNullable(computeClassObjectDescriptor()); + } + }); + this.scopeForClassHeaderResolution = storageManager.createLazyValue(new Computable() { + @Override + public JetScope compute() { + return computeScopeForClassHeaderResolution(); + } + }); + this.scopeForMemberDeclarationResolution = storageManager.createLazyValue(new Computable() { + @Override + public JetScope compute() { + return computeScopeForMemberDeclarationResolution(); + } + }); + this.scopeForPropertyInitializerResolution = storageManager.createLazyValue(new Computable() { + @Override + public JetScope compute() { + return computeScopeForPropertyInitializerResolution(); + } + }); } @Override @@ -126,59 +168,67 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc @NotNull public JetScope getScopeForClassHeaderResolution() { - if (scopeForClassHeaderResolution == null) { - WritableScopeImpl scope = new WritableScopeImpl( - JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Class Header Resolution"); - for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) { - scope.addClassifierDescriptor(typeParameterDescriptor); - } - scope.changeLockLevel(WritableScope.LockLevel.READING); - - PsiElement scopeAnchor = declarationProvider.getOwnerInfo().getScopeAnchor(); - scopeForClassHeaderResolution = new ChainedScope( - this, - "ScopeForClassHeaderResolution: " + getName(), - scope, getScopeProvider().getResolutionScopeForDeclaration(scopeAnchor)); - } - return scopeForClassHeaderResolution; + return scopeForClassHeaderResolution.get(); } + @NotNull + private JetScope computeScopeForClassHeaderResolution() { + WritableScopeImpl scope = new WritableScopeImpl( + JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Class Header Resolution"); + for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) { + scope.addClassifierDescriptor(typeParameterDescriptor); + } + scope.changeLockLevel(WritableScope.LockLevel.READING); + + PsiElement scopeAnchor = declarationProvider.getOwnerInfo().getScopeAnchor(); + return new ChainedScope( + this, + "ScopeForClassHeaderResolution: " + getName(), + scope, getScopeProvider().getResolutionScopeForDeclaration(scopeAnchor)); + } + + @NotNull public JetScope getScopeForMemberDeclarationResolution() { - if (scopeForMemberDeclarationResolution == null) { - WritableScopeImpl scope = new WritableScopeImpl( - JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Member Declaration Resolution"); - scope.addLabeledDeclaration(this); - scope.changeLockLevel(WritableScope.LockLevel.READING); - - scopeForMemberDeclarationResolution = new ChainedScope( - this, - "ScopeForMemberDeclarationResolution: " + getName(), - scope, getScopeForMemberLookup(), getScopeForClassHeaderResolution()); - } - return scopeForMemberDeclarationResolution; + return scopeForMemberDeclarationResolution.get(); } + @NotNull + private JetScope computeScopeForMemberDeclarationResolution() { + WritableScopeImpl scope = new WritableScopeImpl( + JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Member Declaration Resolution"); + scope.addLabeledDeclaration(this); + scope.changeLockLevel(WritableScope.LockLevel.READING); + + return new ChainedScope( + this, + "ScopeForMemberDeclarationResolution: " + getName(), + scope, getScopeForMemberLookup(), getScopeForClassHeaderResolution()); + } + + @NotNull public JetScope getScopeForPropertyInitializerResolution() { + return scopeForPropertyInitializerResolution.get(); + } + + @NotNull + private JetScope computeScopeForPropertyInitializerResolution() { ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor(); if (primaryConstructor == null) return getScopeForMemberDeclarationResolution(); - if (scopeForPropertyInitializerResolution == null) { - WritableScopeImpl scope = new WritableScopeImpl( - JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Property Initializer Resolution"); + WritableScopeImpl scope = new WritableScopeImpl( + JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Property Initializer Resolution"); - List parameters = primaryConstructor.getValueParameters(); - for (ValueParameterDescriptor valueParameterDescriptor : parameters) { - scope.addVariableDescriptor(valueParameterDescriptor); - } - - scope.changeLockLevel(WritableScope.LockLevel.READING); - - scopeForPropertyInitializerResolution = new ChainedScope( - this, - "ScopeForPropertyInitializerResolution: " + getName(), - scope, getScopeForMemberDeclarationResolution()); + List parameters = primaryConstructor.getValueParameters(); + for (ValueParameterDescriptor valueParameterDescriptor : parameters) { + scope.addVariableDescriptor(valueParameterDescriptor); } - return scopeForPropertyInitializerResolution; + + scope.changeLockLevel(WritableScope.LockLevel.READING); + + return new ChainedScope( + this, + "ScopeForPropertyInitializerResolution: " + getName(), + scope, getScopeForMemberDeclarationResolution()); } @NotNull @@ -223,16 +273,18 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc @Override public ClassDescriptor getClassObjectDescriptor() { - if (!classObjectDescriptorResolved) { - JetClassObject classObject = declarationProvider.getOwnerInfo().getClassObject(); + return classObjectDescriptor.get().orNull(); + } - JetClassLikeInfo classObjectInfo = getClassObjectInfo(classObject); - if (classObjectInfo != null) { - classObjectDescriptor = new LazyClassDescriptor(resolveSession, this, getClassObjectName(getName()), classObjectInfo); - } - classObjectDescriptorResolved = true; + @Nullable + private ClassDescriptor computeClassObjectDescriptor() { + JetClassObject classObject = declarationProvider.getOwnerInfo().getClassObject(); + + JetClassLikeInfo classObjectInfo = getClassObjectInfo(classObject); + if (classObjectInfo != null) { + return new LazyClassDescriptor(resolveSession, this, getClassObjectName(getName()), classObjectInfo); } - return classObjectDescriptor; + return null; } @Nullable @@ -281,27 +333,26 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc @NotNull @Override public ReceiverParameterDescriptor getThisAsReceiverParameter() { - if (thisAsReceiverParameter == null) { - thisAsReceiverParameter = DescriptorResolver.createLazyReceiverParameterDescriptor(this); - } - return thisAsReceiverParameter; + return thisAsReceiverParameter.get(); } @Override public List getAnnotations() { - if (annotations == null) { - JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo(); - JetModifierList modifierList = classInfo.getModifierList(); - if (modifierList != null) { - AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver(); - JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(classInfo.getScopeAnchor()); - annotations = annotationResolver.resolveAnnotations(scopeForDeclaration, modifierList, resolveSession.getTrace()); - } - else { - annotations = Collections.emptyList(); - } + return annotations.get(); + } + + @NotNull + private List resolveAnnotations() { + JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo(); + JetModifierList modifierList = classInfo.getModifierList(); + if (modifierList != null) { + AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver(); + JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(classInfo.getScopeAnchor()); + return annotationResolver.resolveAnnotations(scopeForDeclaration, modifierList, resolveSession.getTrace()); + } + else { + return Collections.emptyList(); } - return annotations; } @NotNull @@ -339,35 +390,16 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc } private class LazyClassTypeConstructor implements LazyDescriptor, TypeConstructor { - private Collection supertypes = null; - private List parameters = null; - - @NotNull - @Override - public List getParameters() { - if (parameters == null) { - JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo(); - List typeParameters = classInfo.getTypeParameters(); - parameters = new ArrayList(typeParameters.size()); - - for (int i = 0; i < typeParameters.size(); i++) { - parameters.add(new LazyTypeParameterDescriptor(resolveSession, LazyClassDescriptor.this, typeParameters.get(i), i)); - } - } - return parameters; - } - - @NotNull - @Override - public Collection getSupertypes() { - if (supertypes == null) { + private final LazyValue> supertypes = resolveSession.getStorageManager().createLazyValue(new Computable>() { + @Override + public Collection compute() { if (resolveSession.isClassSpecial(DescriptorUtils.getFQName(LazyClassDescriptor.this))) { - this.supertypes = Collections.emptyList(); + return Collections.emptyList(); } else { JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject(); if (classOrObject == null) { - this.supertypes = Collections.emptyList(); + return Collections.emptyList(); } else { List allSupertypes = resolveSession.getInjector().getDescriptorResolver() @@ -375,12 +407,38 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc LazyClassDescriptor.this, classOrObject, resolveSession.getTrace()); List validSupertypes = Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE)); - this.supertypes = validSupertypes; + findAndDisconnectLoopsInTypeHierarchy(validSupertypes); + return validSupertypes; } } } - return supertypes; + }); + private final LazyValue> parameters = resolveSession.getStorageManager().createLazyValue(new Computable>() { + @Override + public List compute() { + JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo(); + List typeParameters = classInfo.getTypeParameters(); + + List parameters = new ArrayList(typeParameters.size()); + for (int i = 0; i < typeParameters.size(); i++) { + parameters.add(new LazyTypeParameterDescriptor(resolveSession, LazyClassDescriptor.this, typeParameters.get(i), i)); + } + + return parameters; + } + }); + + @NotNull + @Override + public List getParameters() { + return parameters.get(); + } + + @NotNull + @Override + public Collection getSupertypes() { + return supertypes.get(); } private void findAndDisconnectLoopsInTypeHierarchy(List supertypes) {