diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LockBasedStorageManager.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LockBasedStorageManager.java index 18c583d88c3..df0a51889a6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LockBasedStorageManager.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LockBasedStorageManager.java @@ -19,7 +19,13 @@ package org.jetbrains.jet.lang.resolve.lazy; import com.intellij.openapi.util.Computable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; +import org.jetbrains.jet.util.slicedmap.WritableSlice; +import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -44,6 +50,14 @@ public class LockBasedStorageManager implements StorageManager { return new LockBasedLazyValue(lock, computable); } + @NotNull + @Override + 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(lock, originalTrace); + } + private static class LockBasedLazyValue implements LazyValue { private final Object lock; private final Computable computable; @@ -74,4 +88,58 @@ public class LockBasedStorageManager implements StorageManager { } } } + + private static class LockProtectedTrace implements BindingTrace { + private final Object lock; + private final BindingTrace trace; + + public LockProtectedTrace(@NotNull Object lock, @NotNull BindingTrace trace) { + this.lock = lock; + this.trace = trace; + } + + @Override + public BindingContext getBindingContext() { + synchronized (lock) { + return trace.getBindingContext(); + } + } + + @Override + public void record(WritableSlice slice, K key, V value) { + synchronized (lock) { + trace.record(slice, key, value); + } + } + + @Override + public void record(WritableSlice slice, K key) { + synchronized (lock) { + trace.record(slice, key); + } + } + + @Override + @Nullable + public V get(ReadOnlySlice slice, K key) { + synchronized (lock) { + return trace.get(slice, key); + } + } + + @Override + @NotNull + public Collection getKeys(WritableSlice slice) { + synchronized (lock) { + return trace.getKeys(slice); + } + } + + @Override + public void report(@NotNull Diagnostic diagnostic) { + synchronized (lock) { + trace.report(diagnostic); + } + } + } } 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 97a27ac3acf..1dfbfd7fd69 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 @@ -107,7 +107,7 @@ public class ResolveSession { this.storageManager = storageManager; this.classifierAliases = classifierAliases; this.specialClasses = specialClasses; - this.trace = new ObservableBindingTrace(delegationTrace); + this.trace = storageManager.createSafeTrace(delegationTrace); this.injector = new InjectorForLazyResolve(project, this, trace, moduleConfiguration); this.module = rootDescriptor; this.moduleConfiguration = moduleConfiguration; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/StorageManager.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/StorageManager.java index 893a65c9ebd..6f553db0ecd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/StorageManager.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/StorageManager.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.lazy; import com.intellij.openapi.util.Computable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.resolve.BindingTrace; import java.util.concurrent.ConcurrentMap; @@ -27,4 +28,7 @@ public interface StorageManager { @NotNull LazyValue createLazyValue(@NotNull Computable computable); + + @NotNull + BindingTrace createSafeTrace(@NotNull BindingTrace originalTrace); }