diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java index 064c022ba48..5b3c0f003b6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java @@ -117,8 +117,9 @@ public class ResolveSession implements KotlinCodeAnalyzer { @NotNull DeclarationProviderFactory declarationProviderFactory, @NotNull BindingTrace delegationTrace ) { - LockBasedLazyResolveStorageManager lockBasedLazyResolveStorageManager = new LockBasedLazyResolveStorageManager( - (LockBasedStorageManager) globalContext.getStorageManager()); + LockBasedLazyResolveStorageManager lockBasedLazyResolveStorageManager = + new LockBasedLazyResolveStorageManager(globalContext.getStorageManager()); + this.storageManager = lockBasedLazyResolveStorageManager; this.exceptionTracker = globalContext.getExceptionTracker(); this.trace = lockBasedLazyResolveStorageManager.createSafeTrace(delegationTrace); diff --git a/compiler/frontend/src/org/jetbrains/jet/storage/LockBasedLazyResolveStorageManager.java b/compiler/frontend/src/org/jetbrains/jet/storage/LockBasedLazyResolveStorageManager.java index a2ad670a8bd..e0f738e5aaa 100644 --- a/compiler/frontend/src/org/jetbrains/jet/storage/LockBasedLazyResolveStorageManager.java +++ b/compiler/frontend/src/org/jetbrains/jet/storage/LockBasedLazyResolveStorageManager.java @@ -32,15 +32,15 @@ import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; import org.jetbrains.jet.util.slicedmap.WritableSlice; import java.util.Collection; -import java.util.concurrent.locks.Lock; +import java.util.concurrent.ConcurrentMap; // This class is kept under the same package as LockBasedStorageManager to get access to its protected members // Otherwise wed have to expose the lock which is worse than have such a hackish class placement public class LockBasedLazyResolveStorageManager implements LazyResolveStorageManager { - private final LockBasedStorageManager storageManager; + private final StorageManager storageManager; - public LockBasedLazyResolveStorageManager(@NotNull LockBasedStorageManager storageManager) { + public LockBasedLazyResolveStorageManager(@NotNull StorageManager storageManager) { this.storageManager = storageManager; } @@ -65,7 +65,24 @@ public class LockBasedLazyResolveStorageManager implements LazyResolveStorageMan public BindingTrace createSafeTrace(@NotNull BindingTrace originalTrace) { // It seems safe to have a separate lock for traces: // no other locks will be acquired inside the trace operations - return new LockProtectedTrace(storageManager.lock, originalTrace); + + return new LockProtectedTrace(storageManager, originalTrace); + } + + @NotNull + @Override + public MemoizedFunctionToNullable createMemoizedFunctionWithNullableValues( + @NotNull Function1 compute, @NotNull ConcurrentMap map + ) { + return storageManager.createMemoizedFunctionWithNullableValues(compute, map); + } + + @NotNull + @Override + public MemoizedFunctionToNotNull createMemoizedFunction( + @NotNull Function1 compute, @NotNull ConcurrentMap map + ) { + return storageManager.createMemoizedFunction(compute, map); } @NotNull @@ -135,73 +152,69 @@ public class LockBasedLazyResolveStorageManager implements LazyResolveStorageMan } private static class LockProtectedContext implements BindingContext { - private final Lock lock; + private final StorageManager storageManager; private final BindingContext context; - private LockProtectedContext(Lock lock, BindingContext context) { - this.lock = lock; + private LockProtectedContext(StorageManager storageManager, BindingContext context) { + this.storageManager = storageManager; this.context = context; } @NotNull @Override public Diagnostics getDiagnostics() { - lock.lock(); - try { - return context.getDiagnostics(); - } - finally { - lock.unlock(); - } + return storageManager.compute(new Function0() { + @Override + public Diagnostics invoke() { + return context.getDiagnostics(); + } + }); } @Nullable @Override - public V get(ReadOnlySlice slice, K key) { - lock.lock(); - try { - return context.get(slice, key); - } - finally { - lock.unlock(); - } + public V get(final ReadOnlySlice slice, final K key) { + return storageManager.compute(new Function0() { + @Override + public V invoke() { + return context.get(slice, key); + } + }); } @NotNull @Override - public Collection getKeys(WritableSlice slice) { - lock.lock(); - try { - return context.getKeys(slice); - } - finally { - lock.unlock(); - } + public Collection getKeys(final WritableSlice slice) { + return storageManager.compute(new Function0>() { + @Override + public Collection invoke() { + return context.getKeys(slice); + } + }); } @NotNull @Override @TestOnly - public ImmutableMap getSliceContents(@NotNull ReadOnlySlice slice) { - lock.lock(); - try { - return context.getSliceContents(slice); - } - finally { - lock.unlock(); - } + public ImmutableMap getSliceContents(@NotNull final ReadOnlySlice slice) { + return storageManager.compute(new Function0>() { + @Override + public ImmutableMap invoke() { + return context.getSliceContents(slice); + } + }); } } private static class LockProtectedTrace implements BindingTrace { - private final Lock lock; private final BindingTrace trace; private final BindingContext context; + private final StorageManager storageManager; - public LockProtectedTrace(@NotNull Lock lock, @NotNull BindingTrace trace) { - this.lock = lock; + public LockProtectedTrace(@NotNull StorageManager storageManager, @NotNull BindingTrace trace) { + this.storageManager = storageManager; this.trace = trace; - this.context = new LockProtectedContext(lock, trace.getBindingContext()); + this.context = new LockProtectedContext(storageManager, trace.getBindingContext()); } @NotNull @@ -211,60 +224,58 @@ public class LockBasedLazyResolveStorageManager implements LazyResolveStorageMan } @Override - public void record(WritableSlice slice, K key, V value) { - lock.lock(); - try { - trace.record(slice, key, value); - } - finally { - lock.unlock(); - } + public void record(final WritableSlice slice, final K key, final V value) { + storageManager.compute(new Function0() { + @Override + public Unit invoke() { + trace.record(slice, key, value); + return Unit.INSTANCE$; + } + }); } @Override - public void record(WritableSlice slice, K key) { - lock.lock(); - try { - trace.record(slice, key); - } - finally { - lock.unlock(); - } + public void record(final WritableSlice slice, final K key) { + storageManager.compute(new Function0() { + @Override + public Unit invoke() { + trace.record(slice, key); + return Unit.INSTANCE$; + } + }); } @Override @Nullable - public V get(ReadOnlySlice slice, K key) { - lock.lock(); - try { - return trace.get(slice, key); - } - finally { - lock.unlock(); - } + public V get(final ReadOnlySlice slice, final K key) { + return storageManager.compute(new Function0() { + @Override + public V invoke() { + return trace.get(slice, key); + } + }); } @Override @NotNull - public Collection getKeys(WritableSlice slice) { - lock.lock(); - try { - return trace.getKeys(slice); - } - finally { - lock.unlock(); - } + public Collection getKeys(final WritableSlice slice) { + return storageManager.compute(new Function0>() { + @Override + public Collection invoke() { + return trace.getKeys(slice); + } + }); } @Override - public void report(@NotNull Diagnostic diagnostic) { - lock.lock(); - try { - trace.report(diagnostic); - } - finally { - lock.unlock(); - } + public void report(@NotNull final Diagnostic diagnostic) { + storageManager.compute(new Function0() { + @Override + public Unit invoke() { + trace.report(diagnostic); + return Unit.INSTANCE$; + } + }); } } } \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/LoggingStorageManager.kt b/compiler/tests/org/jetbrains/jet/checkers/LoggingStorageManager.kt index 93b4d0f8cc3..c4037cf9a61 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/LoggingStorageManager.kt +++ b/compiler/tests/org/jetbrains/jet/checkers/LoggingStorageManager.kt @@ -23,6 +23,7 @@ import org.jetbrains.jet.storage.MemoizedFunctionToNotNull import org.jetbrains.jet.storage.MemoizedFunctionToNullable import org.jetbrains.jet.storage.NotNullLazyValue import org.jetbrains.jet.storage.NullableLazyValue +import java.util.concurrent.ConcurrentMap public class LoggingStorageManager( private val delegate: StorageManager, @@ -138,6 +139,14 @@ public class LoggingStorageManager( return delegate.createMemoizedFunctionWithNullableValues(compute.logged) } + override fun createMemoizedFunction(compute: (K) -> V, map: ConcurrentMap): MemoizedFunctionToNotNull { + return delegate.createMemoizedFunction(compute.logged, map) + } + + override fun createMemoizedFunctionWithNullableValues(compute: (K) -> V, map: ConcurrentMap): MemoizedFunctionToNullable { + return delegate.createMemoizedFunctionWithNullableValues(compute.logged, map) + } + override fun createLazyValue(computable: () -> T): NotNullLazyValue { return delegate.createLazyValue(computable.logged) } diff --git a/core/util.runtime/src/org/jetbrains/jet/storage/LockBasedStorageManager.java b/core/util.runtime/src/org/jetbrains/jet/storage/LockBasedStorageManager.java index f1a23afb6d6..f1d5df759a3 100644 --- a/core/util.runtime/src/org/jetbrains/jet/storage/LockBasedStorageManager.java +++ b/core/util.runtime/src/org/jetbrains/jet/storage/LockBasedStorageManager.java @@ -30,7 +30,6 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockBasedStorageManager implements StorageManager { - public interface ExceptionHandlingStrategy { ExceptionHandlingStrategy THROW = new ExceptionHandlingStrategy() { @NotNull @@ -105,7 +104,8 @@ public class LockBasedStorageManager implements StorageManager { } @NotNull - protected MemoizedFunctionToNotNull createMemoizedFunction( + @Override + public MemoizedFunctionToNotNull createMemoizedFunction( @NotNull Function1 compute, @NotNull ConcurrentMap map ) { @@ -118,14 +118,9 @@ public class LockBasedStorageManager implements StorageManager { return createMemoizedFunctionWithNullableValues(compute, LockBasedStorageManager.createConcurrentHashMap()); } + @Override @NotNull - private static ConcurrentMap createConcurrentHashMap() { - // memory optimization: fewer segments and entries stored - return new ConcurrentHashMap(3, 1, 2); - } - - @NotNull - protected MemoizedFunctionToNullable createMemoizedFunctionWithNullableValues( + public MemoizedFunctionToNullable createMemoizedFunctionWithNullableValues( @NotNull Function1 compute, @NotNull ConcurrentMap map ) { @@ -221,6 +216,12 @@ public class LockBasedStorageManager implements StorageManager { } } + @NotNull + private static ConcurrentMap createConcurrentHashMap() { + // memory optimization: fewer segments and entries stored + return new ConcurrentHashMap(3, 1, 2); + } + @NotNull protected RecursionDetectedResult recursionDetectedDefault() { throw new IllegalStateException("Recursive call in a lazy value under " + this); diff --git a/core/util.runtime/src/org/jetbrains/jet/storage/StorageManager.kt b/core/util.runtime/src/org/jetbrains/jet/storage/StorageManager.kt index 2bdb6630d97..9f1774de026 100644 --- a/core/util.runtime/src/org/jetbrains/jet/storage/StorageManager.kt +++ b/core/util.runtime/src/org/jetbrains/jet/storage/StorageManager.kt @@ -16,6 +16,7 @@ package org.jetbrains.jet.storage +import java.util.concurrent.ConcurrentMap public trait StorageManager { /** @@ -30,6 +31,10 @@ public trait StorageManager { public fun createMemoizedFunctionWithNullableValues(compute: (K) -> V?): MemoizedFunctionToNullable + public fun createMemoizedFunction(compute: (K) -> V, map: ConcurrentMap): MemoizedFunctionToNotNull + + public fun createMemoizedFunctionWithNullableValues(compute: (K) -> V, map: ConcurrentMap): MemoizedFunctionToNullable + public fun createLazyValue(computable: () -> T): NotNullLazyValue public fun createRecursionTolerantLazyValue(computable: () -> T, onRecursiveCall: T): NotNullLazyValue