Don't memoize exceptions in built-ins resolve session

This commit is contained in:
Nikolay Krasko
2013-08-22 19:13:09 +04:00
parent 6cee65d74e
commit 450d6cad3b
7 changed files with 48 additions and 22 deletions
@@ -86,7 +86,7 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
final PsiClassFinder psiClassFinder = injector.getPsiClassFinder(); final PsiClassFinder psiClassFinder = injector.getPsiClassFinder();
// TODO: Replace with stub declaration provider // TODO: Replace with stub declaration provider
LockBasedStorageManager storageManager = new LockBasedStorageManager(); LockBasedStorageManager storageManager = LockBasedStorageManager.create();
FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(storageManager, files, new Predicate<FqName>() { FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(storageManager, files, new Predicate<FqName>() {
@Override @Override
public boolean apply(FqName fqName) { public boolean apply(FqName fqName) {
@@ -37,6 +37,13 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
public class LockBasedStorageManager implements StorageManager { public class LockBasedStorageManager implements StorageManager {
public static LockBasedStorageManager create() {
return new LockBasedStorageManager(true);
}
public static LockBasedStorageManager createWithoutExceptionMemoization() {
return new LockBasedStorageManager(false);
}
private final Object lock = new Object() { private final Object lock = new Object() {
@Override @Override
@@ -45,13 +52,19 @@ public class LockBasedStorageManager implements StorageManager {
} }
}; };
private final boolean memoizeExceptions;
private LockBasedStorageManager(boolean memoizeExceptions) {
this.memoizeExceptions = memoizeExceptions;
}
@NotNull @NotNull
@Override @Override
public <K, V> MemoizedFunctionToNotNull<K, V> createMemoizedFunction( public <K, V> MemoizedFunctionToNotNull<K, V> createMemoizedFunction(
@NotNull Function<K, V> compute, @NotNull ReferenceKind valuesReferenceKind @NotNull Function<K, V> compute, @NotNull ReferenceKind valuesReferenceKind
) { ) {
ConcurrentMap<K, Object> map = createConcurrentMap(valuesReferenceKind); ConcurrentMap<K, Object> map = createConcurrentMap(valuesReferenceKind);
return new MapBasedMemoizedFunctionToNotNull<K, V>(lock, map, compute); return new MapBasedMemoizedFunctionToNotNull<K, V>(lock, map, compute, memoizeExceptions);
} }
@NotNull @NotNull
@@ -60,7 +73,7 @@ public class LockBasedStorageManager implements StorageManager {
@NotNull Function<K, V> compute, @NotNull ReferenceKind valuesReferenceKind @NotNull Function<K, V> compute, @NotNull ReferenceKind valuesReferenceKind
) { ) {
ConcurrentMap<K, Object> map = createConcurrentMap(valuesReferenceKind); ConcurrentMap<K, Object> map = createConcurrentMap(valuesReferenceKind);
return new MapBasedMemoizedFunction<K, V>(lock, map, compute); return new MapBasedMemoizedFunction<K, V>(lock, map, compute, memoizeExceptions);
} }
private static <K, V> ConcurrentMap<K, V> createConcurrentMap(ReferenceKind referenceKind) { private static <K, V> ConcurrentMap<K, V> createConcurrentMap(ReferenceKind referenceKind) {
@@ -70,13 +83,13 @@ public class LockBasedStorageManager implements StorageManager {
@NotNull @NotNull
@Override @Override
public <T> NotNullLazyValue<T> createLazyValue(@NotNull Computable<T> computable) { public <T> NotNullLazyValue<T> createLazyValue(@NotNull Computable<T> computable) {
return new LockBasedNotNullLazyValue<T>(lock, computable); return new LockBasedNotNullLazyValue<T>(lock, computable, memoizeExceptions);
} }
@NotNull @NotNull
@Override @Override
public <T> NotNullLazyValue<T> createLazyValueWithPostCompute(@NotNull Computable<T> computable, @NotNull final Consumer<T> postCompute) { public <T> NotNullLazyValue<T> createLazyValueWithPostCompute(@NotNull Computable<T> computable, @NotNull final Consumer<T> postCompute) {
return new LockBasedNotNullLazyValue<T>(lock, computable) { return new LockBasedNotNullLazyValue<T>(lock, computable, memoizeExceptions) {
@Override @Override
protected void postCompute(@NotNull T value) { protected void postCompute(@NotNull T value) {
postCompute.consume(value); postCompute.consume(value);
@@ -87,7 +100,7 @@ public class LockBasedStorageManager implements StorageManager {
@NotNull @NotNull
@Override @Override
public <T> NullableLazyValue<T> createNullableLazyValue(@NotNull Computable<T> computable) { public <T> NullableLazyValue<T> createNullableLazyValue(@NotNull Computable<T> computable) {
return new LockBasedLazyValue<T>(lock, computable); return new LockBasedLazyValue<T>(lock, computable, memoizeExceptions);
} }
@NotNull @NotNull
@@ -95,7 +108,7 @@ public class LockBasedStorageManager implements StorageManager {
public <T> NullableLazyValue<T> createNullableLazyValueWithPostCompute( public <T> NullableLazyValue<T> createNullableLazyValueWithPostCompute(
@NotNull Computable<T> computable, @NotNull final Consumer<T> postCompute @NotNull Computable<T> computable, @NotNull final Consumer<T> postCompute
) { ) {
return new LockBasedLazyValue<T>(lock, computable) { return new LockBasedLazyValue<T>(lock, computable, memoizeExceptions) {
@Override @Override
protected void postCompute(@Nullable T value) { protected void postCompute(@Nullable T value) {
postCompute.consume(value); postCompute.consume(value);
@@ -121,13 +134,15 @@ public class LockBasedStorageManager implements StorageManager {
private static class LockBasedLazyValue<T> implements NullableLazyValue<T> { private static class LockBasedLazyValue<T> implements NullableLazyValue<T> {
private final Object lock; private final Object lock;
private final Computable<T> computable; private final Computable<T> computable;
private final boolean memoizeExceptions;
@Nullable @Nullable
private volatile Object value = null; private volatile Object value = null;
public LockBasedLazyValue(@NotNull Object lock, @NotNull Computable<T> computable) { public LockBasedLazyValue(@NotNull Object lock, @NotNull Computable<T> computable, boolean memoizeExceptions) {
this.lock = lock; this.lock = lock;
this.computable = computable; this.computable = computable;
this.memoizeExceptions = memoizeExceptions;
} }
@Override @Override
@@ -146,7 +161,9 @@ public class LockBasedStorageManager implements StorageManager {
return typedValue; return typedValue;
} }
catch (Throwable throwable) { catch (Throwable throwable) {
value = WrappedValues.escapeThrowable(throwable); if (memoizeExceptions) {
value = WrappedValues.escapeThrowable(throwable);
}
throw ExceptionUtils.rethrow(throwable); throw ExceptionUtils.rethrow(throwable);
} }
} }
@@ -159,8 +176,8 @@ public class LockBasedStorageManager implements StorageManager {
private static class LockBasedNotNullLazyValue<T> extends LockBasedLazyValue<T> implements NotNullLazyValue<T> { private static class LockBasedNotNullLazyValue<T> extends LockBasedLazyValue<T> implements NotNullLazyValue<T> {
public LockBasedNotNullLazyValue(@NotNull Object lock, @NotNull Computable<T> computable) { public LockBasedNotNullLazyValue(@NotNull Object lock, @NotNull Computable<T> computable, boolean memoizeExceptions) {
super(lock, computable); super(lock, computable, memoizeExceptions);
} }
@Override @Override
@@ -176,11 +193,15 @@ public class LockBasedStorageManager implements StorageManager {
private final Object lock; private final Object lock;
private final ConcurrentMap<K, Object> cache; private final ConcurrentMap<K, Object> cache;
private final Function<K, V> compute; private final Function<K, V> compute;
private final boolean memoizeExceptions;
public MapBasedMemoizedFunction(@NotNull Object lock, @NotNull ConcurrentMap<K, Object> map, @NotNull Function<K, V> compute) { public MapBasedMemoizedFunction(
@NotNull Object lock, @NotNull ConcurrentMap<K, Object> map,
@NotNull Function<K, V> compute, boolean memoizeExceptions) {
this.lock = lock; this.lock = lock;
this.cache = map; this.cache = map;
this.compute = compute; this.compute = compute;
this.memoizeExceptions = memoizeExceptions;
} }
@Override @Override
@@ -201,8 +222,10 @@ public class LockBasedStorageManager implements StorageManager {
return typedValue; return typedValue;
} }
catch (Throwable throwable) { catch (Throwable throwable) {
Object oldValue = cache.put(input, WrappedValues.escapeThrowable(throwable)); if (memoizeExceptions) {
assert oldValue == null : "Race condition detected"; Object oldValue = cache.put(input, WrappedValues.escapeThrowable(throwable));
assert oldValue == null : "Race condition detected";
}
throw ExceptionUtils.rethrow(throwable); throw ExceptionUtils.rethrow(throwable);
} }
@@ -215,9 +238,10 @@ public class LockBasedStorageManager implements StorageManager {
public MapBasedMemoizedFunctionToNotNull( public MapBasedMemoizedFunctionToNotNull(
@NotNull Object lock, @NotNull Object lock,
@NotNull ConcurrentMap<K, Object> map, @NotNull ConcurrentMap<K, Object> map,
@NotNull Function<K, V> compute @NotNull Function<K, V> compute,
boolean memoizeExceptions
) { ) {
super(lock, map, compute); super(lock, map, compute, memoizeExceptions);
} }
@NotNull @NotNull
@@ -324,5 +348,4 @@ public class LockBasedStorageManager implements StorageManager {
} }
} }
} }
} }
@@ -238,7 +238,10 @@ public class KotlinBuiltIns {
@NotNull @NotNull
private KotlinCodeAnalyzer createLazyResolveSession(@NotNull Project project) throws IOException { private KotlinCodeAnalyzer createLazyResolveSession(@NotNull Project project) throws IOException {
List<JetFile> files = loadResourcesAsJetFiles(project, LIBRARY_FILES); List<JetFile> files = loadResourcesAsJetFiles(project, LIBRARY_FILES);
LockBasedStorageManager storageManager = new LockBasedStorageManager();
// As builtins resolve session is never recreated, we don't want it be corrupted forever with stored exceptions
LockBasedStorageManager storageManager = LockBasedStorageManager.createWithoutExceptionMemoization();
return new ResolveSession( return new ResolveSession(
project, project,
storageManager, storageManager,
@@ -56,7 +56,7 @@ public abstract class AbstractLazyResolveDescriptorRendererTest extends KotlinTe
ModuleDescriptorImpl lazyModule = AnalyzerFacadeForJVM.createJavaModule("<lazy module>"); ModuleDescriptorImpl lazyModule = AnalyzerFacadeForJVM.createJavaModule("<lazy module>");
lazyModule.setModuleConfiguration(injectorForTopDownAnalyzer.getModuleDescriptor().getModuleConfiguration()); lazyModule.setModuleConfiguration(injectorForTopDownAnalyzer.getModuleDescriptor().getModuleConfiguration());
LockBasedStorageManager storageManager = new LockBasedStorageManager(); LockBasedStorageManager storageManager = LockBasedStorageManager.create();
final ResolveSession resolveSession = new ResolveSession(getProject(), storageManager, lazyModule, final ResolveSession resolveSession = new ResolveSession(getProject(), storageManager, lazyModule,
new FileBasedDeclarationProviderFactory(storageManager, files)); new FileBasedDeclarationProviderFactory(storageManager, files));
@@ -100,7 +100,7 @@ public class LazyResolveTestUtil {
final JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver(); final JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver();
LockBasedStorageManager storageManager = new LockBasedStorageManager(); LockBasedStorageManager storageManager = LockBasedStorageManager.create();
FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(storageManager, files, new Predicate<FqName>() { FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(storageManager, files, new Predicate<FqName>() {
@Override @Override
public boolean apply(FqName fqName) { public boolean apply(FqName fqName) {
@@ -214,7 +214,7 @@ public class JetSourceNavigationHelper {
} }
Project project = decompiledDeclaration.getProject(); Project project = decompiledDeclaration.getProject();
LockBasedStorageManager storageManager = new LockBasedStorageManager(); LockBasedStorageManager storageManager = LockBasedStorageManager.create();
FileBasedDeclarationProviderFactory providerFactory = new FileBasedDeclarationProviderFactory(storageManager, getContainingFiles(candidates), FileBasedDeclarationProviderFactory providerFactory = new FileBasedDeclarationProviderFactory(storageManager, getContainingFiles(candidates),
new Predicate<FqName>() { new Predicate<FqName>() {
@Override @Override
@@ -140,7 +140,7 @@ public final class AnalyzerFacadeForJS {
@NotNull @NotNull
public static ResolveSession getLazyResolveSession(Collection<JetFile> files, Config config) { public static ResolveSession getLazyResolveSession(Collection<JetFile> files, Config config) {
LockBasedStorageManager storageManager = new LockBasedStorageManager(); LockBasedStorageManager storageManager = LockBasedStorageManager.create();
FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory( FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(
storageManager, Config.withJsLibAdded(files, config), Predicates.<FqName>alwaysFalse()); storageManager, Config.withJsLibAdded(files, config), Predicates.<FqName>alwaysFalse());
ModuleDescriptorImpl lazyModule = createJsModule("<lazy module>"); ModuleDescriptorImpl lazyModule = createJsModule("<lazy module>");