diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializationBindings.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializationBindings.java index 84e2889feda..35c6c550854 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializationBindings.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializationBindings.java @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.codegen; import com.intellij.openapi.util.Pair; +import kotlin.Function3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; @@ -28,7 +29,6 @@ import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.commons.Method; import java.util.Collection; -import java.util.Map; public final class JvmSerializationBindings { public static final SerializationMappingSlice METHOD_FOR_FUNCTION = @@ -82,13 +82,18 @@ public final class JvmSerializationBindings { @NotNull public static JvmSerializationBindings union(@NotNull Collection bindings) { - MutableSlicedMap result = SlicedMapImpl.create(); + final MutableSlicedMap result = SlicedMapImpl.create(); + for (JvmSerializationBindings binding : bindings) { - for (Map.Entry, ?> entry : binding.map) { - SlicedMapKey key = entry.getKey(); - result.put((WritableSlice) key.getSlice(), key.getKey(), entry.getValue()); - } + binding.map.forEach(new Function3() { + @Override + public Void invoke(WritableSlice slice, Object key, Object value) { + result.put(slice, key, value); + return null; + } + }); } + return new JvmSerializationBindings(result); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatingBindingTrace.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatingBindingTrace.java index d1adff35931..b45e7b9f3d7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatingBindingTrace.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatingBindingTrace.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import kotlin.Function3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; @@ -161,19 +162,17 @@ public class DelegatingBindingTrace implements BindingTrace { clear(); } - public void addAllMyDataTo(@NotNull BindingTrace trace, @Nullable TraceEntryFilter filter, boolean commitDiagnostics) { - for (Map.Entry, ?> entry : map) { - SlicedMapKey slicedMapKey = entry.getKey(); + public void addAllMyDataTo(@NotNull final BindingTrace trace, @Nullable final TraceEntryFilter filter, boolean commitDiagnostics) { + map.forEach(new Function3() { + @Override + public Void invoke(WritableSlice slice, Object key, Object value) { + if (filter == null || filter.accept(slice, key)) { + trace.record(slice, key, value); + } - WritableSlice slice = slicedMapKey.getSlice(); - Object key = slicedMapKey.getKey(); - Object value = entry.getValue(); - - if (filter == null || filter.accept(slice, key)) { - //noinspection unchecked - trace.record(slice, key, value); + return null; } - } + }); if (!commitDiagnostics) return; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/BasicWritableSlice.java b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/BasicWritableSlice.java index 0e8fc7ff6e3..e08ec29385d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/BasicWritableSlice.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/BasicWritableSlice.java @@ -16,12 +16,13 @@ package org.jetbrains.kotlin.util.slicedMap; +import com.intellij.openapi.util.Key; import org.jetbrains.annotations.NotNull; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -public class BasicWritableSlice implements WritableSlice { +public class BasicWritableSlice extends Key implements WritableSlice { public static Void initSliceDebugNames(Class declarationOwner) { for (Field field : declarationOwner.getFields()) { @@ -48,13 +49,16 @@ public class BasicWritableSlice implements WritableSlice { } public BasicWritableSlice(RewritePolicy rewritePolicy, boolean isCollective) { + super(""); + this.rewritePolicy = rewritePolicy; this.isCollective = isCollective; } @Override - public SlicedMapKey makeKey(K key) { - return new SlicedMapKey(this, key); + @NotNull + public Key getKey() { + return this; } // True to put, false to skip diff --git a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/DelegatingSlice.java b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/DelegatingSlice.java index 71a69887ec7..6a58a3b0103 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/DelegatingSlice.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/DelegatingSlice.java @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.util.slicedMap; +import com.intellij.openapi.util.Key; import org.jetbrains.annotations.NotNull; /** @@ -49,8 +50,9 @@ public class DelegatingSlice implements WritableSlice { } @Override - public SlicedMapKey makeKey(K key) { - return delegate.makeKey(key); + @NotNull + public Key getKey() { + return delegate.getKey(); } @Override diff --git a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/ReadOnlySlice.java b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/ReadOnlySlice.java index d12b83b5331..2157f21a880 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/ReadOnlySlice.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/ReadOnlySlice.java @@ -16,8 +16,12 @@ package org.jetbrains.kotlin.util.slicedMap; +import com.intellij.openapi.util.Key; +import org.jetbrains.annotations.NotNull; + public interface ReadOnlySlice { - SlicedMapKey makeKey(K key); + @NotNull + Key getKey(); V computeValue(SlicedMap map, K key, V value, boolean valueNotFound); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/SlicedMap.java b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/SlicedMap.java index 23f2a261fb2..affc58d0c67 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/SlicedMap.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/SlicedMap.java @@ -16,12 +16,13 @@ package org.jetbrains.kotlin.util.slicedMap; +import kotlin.Function3; +import org.jetbrains.annotations.NotNull; + import java.util.Collection; import java.util.Collections; -import java.util.Iterator; -import java.util.Map; -public interface SlicedMap extends Iterable, ?>> { +public interface SlicedMap { SlicedMap DO_NOTHING = new SlicedMap() { @Override @@ -35,8 +36,7 @@ public interface SlicedMap extends Iterable, ?>> { } @Override - public Iterator, ?>> iterator() { - return Collections., ?>>emptySet().iterator(); + public void forEach(@NotNull Function3 f) { } }; @@ -44,4 +44,6 @@ public interface SlicedMap extends Iterable, ?>> { // slice.isCollective() must return true Collection getKeys(WritableSlice slice); + + void forEach(@NotNull Function3 f); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/SlicedMapImpl.java b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/SlicedMapImpl.java index fdf61422231..fc23f100d01 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/SlicedMapImpl.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/SlicedMapImpl.java @@ -18,47 +18,48 @@ package org.jetbrains.kotlin.util.slicedMap; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import com.google.common.collect.Multimap; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolder; +import gnu.trove.THashMap; +import gnu.trove.TIntObjectHashMap; +import kotlin.Function3; import org.jetbrains.annotations.NotNull; import java.util.Collection; -import java.util.Iterator; import java.util.Map; public class SlicedMapImpl implements MutableSlicedMap { + private static final TIntObjectHashMap keyIdToSlice = new TIntObjectHashMap(); + public static SlicedMapImpl create() { - return new SlicedMapImpl(Maps., Object>newLinkedHashMap()); + return new SlicedMapImpl(); } - public static SlicedMapImpl create(Map, Object> map) { - return new SlicedMapImpl(map); - } - - public static SlicedMapImpl create(MapSupplier mapSupplier) { - return new SlicedMapImpl(mapSupplier., Object>get()); - } - - private final Map, Object> map; + private final Map map = new THashMap(0); private final Multimap, Object> collectiveSliceKeys = ArrayListMultimap.create(); - protected SlicedMapImpl(Map, Object> map) { - this.map = map; - } - @Override public void put(WritableSlice slice, K key, V value) { if (!slice.check(key, value)) { return; } - SlicedMapKey slicedMapKey = slice.makeKey(key); + UserDataHolderImpl holder = map.get(key); + if (holder == null) { + holder = new UserDataHolderImpl(); + map.put(key, holder); + } + + Key sliceKey = slice.getKey(); + RewritePolicy rewritePolicy = slice.getRewritePolicy(); if (rewritePolicy.rewriteProcessingNeeded(key)) { - if (map.containsKey(slicedMapKey)) { + V oldValue = holder.getUserData(sliceKey); + if (oldValue != null) { //noinspection unchecked - if (!rewritePolicy.processRewrite(slice, key, (V) map.get(slicedMapKey), value)) { + if (!rewritePolicy.processRewrite(slice, key, oldValue, value)) { return; } } @@ -68,7 +69,12 @@ public class SlicedMapImpl implements MutableSlicedMap { collectiveSliceKeys.put(slice, key); } - map.put(slicedMapKey, value); + int sliceKeyId = sliceKey.hashCode(); + if (!keyIdToSlice.contains(sliceKeyId)) { + keyIdToSlice.put(sliceKeyId, slice); + } + + holder.putUserData(sliceKey, value); slice.afterPut(this, key, value); } @@ -79,10 +85,11 @@ public class SlicedMapImpl implements MutableSlicedMap { @Override public V get(ReadOnlySlice slice, K key) { - SlicedMapKey slicedMapKey = slice.makeKey(key); - //noinspection unchecked - V value = (V) map.get(slicedMapKey); - return slice.computeValue(this, key, value, value == null && !map.containsKey(slicedMapKey)); + UserDataHolderImpl holder = map.get(key); + + V value = holder == null ? null : holder.getUserData(slice.getKey()); + + return slice.computeValue(this, key, value, value == null); } @Override @@ -94,24 +101,53 @@ public class SlicedMapImpl implements MutableSlicedMap { @Override public V remove(RemovableSlice slice, K key) { - //noinspection unchecked - return (V) map.remove(slice.makeKey(key)); + UserDataHolderImpl holder = map.get(key); + + if (holder == null) return null; + + Key sliceKey = slice.getKey(); + V value = holder.getUserData(sliceKey); + + holder.putUserData(sliceKey, null); + + if (holder.isUserDataEmpty()) { + map.remove(key); + } + + return value; } - @NotNull @Override - public Iterator, ?>> iterator() { - //noinspection unchecked - return (Iterator) map.entrySet().iterator(); + public void forEach(@NotNull Function3 f) { + for (Map.Entry entry : map.entrySet()) { + Object key = entry.getKey(); + UserDataHolderImpl holder = entry.getValue(); + + if (holder == null) continue; + + for (Key sliceKey : holder.getKeys()) { + WritableSlice slice = keyIdToSlice.get(sliceKey.hashCode()); + Object value = holder.getUserData(sliceKey); + + f.invoke(slice, key, value); + } + } } @NotNull @Override public ImmutableMap getSliceContents(@NotNull ReadOnlySlice slice) { ImmutableMap.Builder builder = ImmutableMap.builder(); - for (Map.Entry, ?> entry : map.entrySet()) { - if (entry.getKey().getSlice() == slice) { - builder.put((K) entry.getKey().getKey(), (V) entry.getValue()); + + for (Map.Entry entry : map.entrySet()) { + + UserDataHolder holder = entry.getValue(); + + V value = holder.getUserData(slice.getKey()); + + if (value != null) { + //noinspection unchecked + builder.put((K) entry.getKey(), value); } } return builder.build(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/SlicedMapKey.java b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/SlicedMapKey.java deleted file mode 100644 index 1cefeff2a6c..00000000000 --- a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/SlicedMapKey.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.util.slicedMap; - -import org.jetbrains.annotations.NotNull; - -public final class SlicedMapKey { - - private final WritableSlice slice; - private final K key; - - public SlicedMapKey(@NotNull WritableSlice slice, K key) { - this.slice = slice; - this.key = key; - } - - public WritableSlice getSlice() { - return slice; - } - - public K getKey() { - return key; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof SlicedMapKey)) return false; - - SlicedMapKey that = (SlicedMapKey) o; - - if (key != null ? !key.equals(that.key) : that.key != null) return false; - if (!slice.equals(that.slice)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = slice.hashCode(); - result = 31 * result + (key != null ? key.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return slice + " -> " + key; - } -} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/Slices.java b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/Slices.java index 633e7064e5c..f5bcb047b1a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/Slices.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/Slices.java @@ -186,14 +186,6 @@ public class Slices { map.put(opposite, value, key); } } - @Override - public SlicedMapKey makeKey(K key) { - if (keyNormalizer == null) { - return super.makeKey(key); - } - return super.makeKey(keyNormalizer.normalize(key)); - } - } public static class SetSlice extends BasicRemovableSlice { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/TrackingSlicedMap.java b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/TrackingSlicedMap.java index acc5bf6042e..935608f8130 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/TrackingSlicedMap.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/TrackingSlicedMap.java @@ -18,12 +18,13 @@ package org.jetbrains.kotlin.util.slicedMap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; +import com.intellij.openapi.util.Key; +import kotlin.Function3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly; import org.jetbrains.kotlin.utils.Printer; import java.util.Collection; -import java.util.Iterator; import java.util.Map; public class TrackingSlicedMap extends SlicedMapImpl { @@ -31,7 +32,6 @@ public class TrackingSlicedMap extends SlicedMapImpl { private final boolean trackWithStackTraces; public TrackingSlicedMap(boolean trackWithStackTraces) { - super(Maps., Object>newLinkedHashMap()); this.trackWithStackTraces = trackWithStackTraces; } @@ -55,21 +55,15 @@ public class TrackingSlicedMap extends SlicedMapImpl { return super.getKeys(wrapSlice(slice)); } - @NotNull @Override - public Iterator, ?>> iterator() { - Map, Object> map = Maps.newHashMap(); - - Iterator, ?>> iterator = super.iterator(); - - //noinspection WhileLoopReplaceableByForEach - while (iterator.hasNext()) { - Map.Entry, ?> entry = iterator.next(); - map.put(entry.getKey(), ((TrackableValue) entry.getValue()).value); - } - - //noinspection unchecked - return (Iterator) map.entrySet().iterator(); + public void forEach(@NotNull final Function3 f) { + super.forEach(new Function3() { + @Override + public Void invoke(WritableSlice slice, Object key, Object value) { + f.invoke(slice, key, ((TrackableValue) value).value); + return null; + } + }); } @Override @@ -143,20 +137,21 @@ public class TrackingSlicedMap extends SlicedMapImpl { } } - public class SliceWithStackTrace implements RemovableSlice> { + private class SliceWithStackTrace extends Key> implements RemovableSlice> { private final ReadOnlySlice delegate; private SliceWithStackTrace(@NotNull ReadOnlySlice delegate) { + super(delegate.toString()); this.delegate = delegate; } // Methods of ReadOnlySlice @Override - public SlicedMapKey> makeKey(K key) { - //noinspection unchecked - return (SlicedMapKey) delegate.makeKey(key); + @NotNull + public Key> getKey() { + return this; } @Override diff --git a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/UserDataHolderImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/UserDataHolderImpl.kt new file mode 100644 index 00000000000..4c4d3f6d275 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/UserDataHolderImpl.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.util.slicedMap + +import com.intellij.openapi.util.Key +import org.jetbrains.kotlin.util.userDataHolder.UserDataHolderBase +import org.jetbrains.kotlin.util.userDataHolder.keyFMap.KeyFMap + +class UserDataHolderImpl : UserDataHolderBase() { + val keys: Array> + get() = getUserMap().getKeys() +}