diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/lazy/storage/LockBasedStorageManager.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/lazy/storage/LockBasedStorageManager.java index 2377516dd15..b60c4656974 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/lazy/storage/LockBasedStorageManager.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/lazy/storage/LockBasedStorageManager.java @@ -114,7 +114,7 @@ public class LockBasedStorageManager implements StorageManager { return new LockBasedLazyValue(lock, computable) { @Override protected Object recursionDetected() { - return WrappedValues.escapeNull(onRecursiveCall); + return onRecursiveCall; } }; } @@ -141,13 +141,14 @@ public class LockBasedStorageManager implements StorageManager { private static class LockBasedLazyValue implements NullableLazyValue { + private static final Object NOT_COMPUTED = new Object(); private static final Object COMPUTING = new Object(); private final Object lock; private final Computable computable; @Nullable - private volatile Object value = null; + private volatile Object value = NOT_COMPUTED; public LockBasedLazyValue(@NotNull Object lock, @NotNull Computable computable) { this.lock = lock; @@ -157,23 +158,23 @@ public class LockBasedStorageManager implements StorageManager { @Override public T compute() { Object _value = value; - if (_value != null && _value != COMPUTING) return WrappedValues.unescapeExceptionOrNull(_value); + if (_value != NOT_COMPUTED && _value != COMPUTING) return WrappedValues.unescapeThrowable(_value); synchronized (lock) { _value = value; if (_value == COMPUTING) { Object result = recursionDetected(); - if (result != null) { - return WrappedValues.unescapeExceptionOrNull(result); + if (result != NOT_COMPUTED) { + return WrappedValues.unescapeThrowable(result); } } - if (_value != null) return WrappedValues.unescapeExceptionOrNull(_value); + if (_value != NOT_COMPUTED) return WrappedValues.unescapeThrowable(_value); value = COMPUTING; try { T typedValue = computable.compute(); - value = WrappedValues.escapeNull(typedValue); + value = typedValue; postCompute(typedValue); return typedValue; } @@ -185,7 +186,7 @@ public class LockBasedStorageManager implements StorageManager { } /** - * @return {@code null} to proceed, a wrapped value otherwise, see WrappedValues + * @return {@code NOT_COMPUTED} to proceed, a value or wrapped exception otherwise, see WrappedValues * @throws DO NOT throw exceptions from implementations of this method, instead return WrappedValues.escapeThrowable(exception) */ @Nullable diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/lazy/storage/StorageManager.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/lazy/storage/StorageManager.java index 07e56795951..68ea78bece4 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/lazy/storage/StorageManager.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/lazy/storage/StorageManager.java @@ -44,9 +44,8 @@ public interface StorageManager { /** * @param onRecursiveCall is called if the computation calls itself recursively. - * If this parameter is null, an exception will be thrown on a recursive call. - * If this function returns null, the computation proceeds recursively, - * otherwise it should return a result of WrappedValues.escape*() method + * If this parameter is null, an exception will be thrown on a recursive call, + * otherwise it should return a result of WrappedValues.escapeThrowable() method * @param postCompute is called after the value is computed, but before any other thread sees it (the current thread may * see it in between) */ diff --git a/core/util.runtime/src/org/jetbrains/jet/utils/WrappedValues.java b/core/util.runtime/src/org/jetbrains/jet/utils/WrappedValues.java index c345808d833..9d48919043c 100644 --- a/core/util.runtime/src/org/jetbrains/jet/utils/WrappedValues.java +++ b/core/util.runtime/src/org/jetbrains/jet/utils/WrappedValues.java @@ -58,10 +58,16 @@ public class WrappedValues { @Nullable public static V unescapeExceptionOrNull(@NotNull Object value) { + return unescapeNull(unescapeThrowable(value)); + } + + @Nullable + public static V unescapeThrowable(@Nullable Object value) { if (value instanceof ThrowableWrapper) { throw ExceptionUtils.rethrow(((ThrowableWrapper) value).getThrowable()); } - return unescapeNull(value); + //noinspection unchecked + return (V) value; } }