From 14247ea2abcb1d3d3d82422de41080e52797299f Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Sat, 27 Jul 2013 01:30:29 +0400 Subject: [PATCH] Guard construction of imports index under common lock --- .../lang/resolve/lazy/ImportsProvider.java | 95 +++++++++++-------- .../lang/resolve/lazy/LazyImportScope.java | 2 +- 2 files changed, 55 insertions(+), 42 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ImportsProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ImportsProvider.java index bb122c6ab15..b0e7bb8e4fb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ImportsProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ImportsProvider.java @@ -17,29 +17,35 @@ package org.jetbrains.jet.lang.resolve.lazy; import com.google.common.collect.*; +import com.intellij.openapi.util.Computable; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetImportDirective; import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.ImportPath; +import org.jetbrains.jet.lang.resolve.lazy.storage.NotNullLazyValue; +import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager; import org.jetbrains.jet.lang.resolve.name.Name; -import java.util.*; +import java.util.List; +import java.util.Set; class ImportsProvider { private final List importDirectives; + private final NotNullLazyValue importsCacheValue; - private ListMultimap nameToDirectives = null; - private List allUnderImports = null; - private boolean indexed; - - public ImportsProvider(List importDirectives) { + public ImportsProvider(StorageManager storageManager, final List importDirectives) { this.importDirectives = importDirectives; + this.importsCacheValue = storageManager.createLazyValue(new Computable() { + @Override + public NameToImportsCache compute() { + return NameToImportsCache.createIndex(importDirectives); + } + }); } @NotNull public List getImports(@NotNull Name name) { - createIndex(); - return nameToDirectives.containsKey(name) ? nameToDirectives.get(name) : allUnderImports; + return importsCacheValue.compute().getImports(name); } @NotNull @@ -47,49 +53,56 @@ class ImportsProvider { return importDirectives; } - private void createIndex() { - if (indexed) { - return; + private static class NameToImportsCache { + private final ListMultimap nameToDirectives; + private final List allUnderImports; + + private NameToImportsCache(ListMultimap directives, List imports) { + nameToDirectives = directives; + allUnderImports = imports; } - ImmutableListMultimap.Builder namesToRelativeImportsBuilder = ImmutableListMultimap.builder(); + private List getImports(@NotNull Name name) { + return nameToDirectives.containsKey(name) ? nameToDirectives.get(name) : allUnderImports; + } - Set processedAliases = Sets.newHashSet(); - List processedAllUnderImports = Lists.newArrayList(); + private static NameToImportsCache createIndex(List importDirectives) { + ImmutableListMultimap.Builder namesToRelativeImportsBuilder = ImmutableListMultimap.builder(); - for (JetImportDirective anImport : importDirectives) { - ImportPath path = JetPsiUtil.getImportPath(anImport); - if (path == null) { - // Could be some parse errors - continue; - } + Set processedAliases = Sets.newHashSet(); + List processedAllUnderImports = Lists.newArrayList(); - if (path.isAllUnder()) { - processedAllUnderImports.add(anImport); + for (JetImportDirective anImport : importDirectives) { + ImportPath path = JetPsiUtil.getImportPath(anImport); + if (path == null) { + // Could be some parse errors + continue; + } + + if (path.isAllUnder()) { + processedAllUnderImports.add(anImport); + + // All-Under import is relevant to all names found so far + for (Name aliasName : processedAliases) { + namesToRelativeImportsBuilder.put(aliasName, anImport); + } + } + else { + Name aliasName = path.getImportedName(); + assert aliasName != null; + + if (!processedAliases.contains(aliasName)) { + processedAliases.add(aliasName); + + // Add to relevant imports all all-under imports found by this moment + namesToRelativeImportsBuilder.putAll(aliasName, processedAllUnderImports); + } - // All-Under import is relevant to all names found so far - for (Name aliasName : processedAliases) { namesToRelativeImportsBuilder.put(aliasName, anImport); } } - else { - Name aliasName = path.getImportedName(); - assert aliasName != null; - if (!processedAliases.contains(aliasName)) { - processedAliases.add(aliasName); - - // Add to relevant imports all all-under imports found by this moment - namesToRelativeImportsBuilder.putAll(aliasName, processedAllUnderImports); - } - - namesToRelativeImportsBuilder.put(aliasName, anImport); - } + return new NameToImportsCache(namesToRelativeImportsBuilder.build(), ImmutableList.copyOf(processedAllUnderImports)); } - - allUnderImports = ImmutableList.copyOf(processedAllUnderImports); - nameToDirectives = namesToRelativeImportsBuilder.build(); - - indexed = true; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyImportScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyImportScope.java index 51bebcfbcb2..d353953006f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyImportScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyImportScope.java @@ -126,7 +126,7 @@ public class LazyImportScope implements JetScope { ) { this.resolveSession = resolveSession; this.packageDescriptor = packageDescriptor; - this.importsProvider = new ImportsProvider(imports); + this.importsProvider = new ImportsProvider(resolveSession.getStorageManager(), imports); this.traceForImportResolve = traceForImportResolve; this.debugName = debugName;