mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
interval trees: speed up iteration by making Getter.get hot spot bimorphic instead of megamorphic
GitOrigin-RevId: 5cf5fbd4919e23feef807ed457af9d723e6203c4
This commit is contained in:
committed by
intellij-monorepo-bot
parent
e9771b8129
commit
eaefb91446
@@ -7,6 +7,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.ex.MarkupIterator;
|
||||
import com.intellij.openapi.editor.ex.RangeMarkerEx;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.StaticGetter;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
@@ -164,8 +165,8 @@ abstract class IntervalTreeImpl<T> extends RedBlackTree<T> implements IntervalTr
|
||||
}
|
||||
}
|
||||
|
||||
protected Getter<E> createGetter(@NotNull E interval) {
|
||||
return new WeakReferencedGetter<>(interval, myIntervalTree.myReferenceQueue);
|
||||
private Getter<E> createGetter(@NotNull E interval) {
|
||||
return myIntervalTree.keepIntervalsOnWeakReferences() ? new WeakReferencedGetter<>(interval, myIntervalTree.myReferenceQueue) : new StaticGetter<>(interval);
|
||||
}
|
||||
|
||||
private static class WeakReferencedGetter<T> extends WeakReference<T> implements Getter<T> {
|
||||
@@ -393,6 +394,10 @@ abstract class IntervalTreeImpl<T> extends RedBlackTree<T> implements IntervalTr
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean keepIntervalsOnWeakReferences() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract IntervalNode<T> createNewNode(@NotNull T key, int start, int end,
|
||||
boolean greedyToLeft, boolean greedyToRight, boolean stickingToRight, int layer);
|
||||
|
||||
+1
-7
@@ -12,7 +12,6 @@ import com.intellij.openapi.editor.ex.MarkupModelEx;
|
||||
import com.intellij.openapi.editor.ex.RangeHighlighterEx;
|
||||
import com.intellij.openapi.editor.markup.*;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.util.BitUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
@@ -27,7 +26,7 @@ import java.awt.*;
|
||||
* Implementation of the markup element for the editor and document.
|
||||
* @author max
|
||||
*/
|
||||
class RangeHighlighterImpl extends RangeMarkerImpl implements RangeHighlighterEx, Getter<RangeHighlighterEx> {
|
||||
class RangeHighlighterImpl extends RangeMarkerImpl implements RangeHighlighterEx {
|
||||
@SuppressWarnings({"InspectionUsingGrayColors", "UseJBColor"})
|
||||
private static final Color NULL_COLOR = new Color(0, 0, 0); // must be new instance to work as a sentinel
|
||||
private static final Key<Boolean> VISIBLE_IF_FOLDED = Key.create("visible.folded");
|
||||
@@ -443,11 +442,6 @@ class RangeHighlighterImpl extends RangeMarkerImpl implements RangeHighlighterEx
|
||||
getMarkupModel().removeHighlighter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RangeHighlighterImpl get() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayer() {
|
||||
RangeHighlighterTree.RHNode node = (RangeHighlighterTree.RHNode)(Object)myNode;
|
||||
|
||||
+5
-7
@@ -30,6 +30,11 @@ class RangeHighlighterTree extends RangeMarkerTree<RangeHighlighterEx> {
|
||||
myMarkupModel = markupModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean keepIntervalsOnWeakReferences() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
MarkupIterator<RangeHighlighterEx> overlappingIterator(@NotNull TextRangeInterval rangeInterval, boolean onlyRenderedInGutter) {
|
||||
MarkupIterator<RangeHighlighterEx> iterator =
|
||||
@@ -84,13 +89,6 @@ class RangeHighlighterTree extends RangeMarkerTree<RangeHighlighterEx> {
|
||||
myLayer = layer;
|
||||
}
|
||||
|
||||
//range highlighters are strongly referenced
|
||||
@Override
|
||||
protected Getter<RangeHighlighterEx> createGetter(@NotNull RangeHighlighterEx interval) {
|
||||
//noinspection unchecked
|
||||
return (Getter<RangeHighlighterEx>)interval;
|
||||
}
|
||||
|
||||
private void recalculateRenderFlags() {
|
||||
boolean renderedInGutter = false;
|
||||
for (Getter<RangeHighlighterEx> getter : intervals) {
|
||||
|
||||
+1
-7
@@ -3,10 +3,9 @@ package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.editor.ex.RangeHighlighterEx;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class ErrorStripeMarkerImpl extends RangeMarkerImpl implements Getter<ErrorStripeMarkerImpl> {
|
||||
class ErrorStripeMarkerImpl extends RangeMarkerImpl {
|
||||
|
||||
private final RangeHighlighterEx myHighlighter;
|
||||
|
||||
@@ -20,11 +19,6 @@ class ErrorStripeMarkerImpl extends RangeMarkerImpl implements Getter<ErrorStrip
|
||||
return myHighlighter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorStripeMarkerImpl get() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return myHighlighter.isValid() && super.isValid();
|
||||
|
||||
+1
-6
@@ -2,10 +2,9 @@
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class ErrorStripeRangeMarkerTree extends RangeMarkerTree<ErrorStripeMarkerImpl> {
|
||||
class ErrorStripeRangeMarkerTree extends HardReferencingRangeMarkerTree<ErrorStripeMarkerImpl> {
|
||||
|
||||
ErrorStripeRangeMarkerTree(@NotNull Document document) {
|
||||
super(document);
|
||||
@@ -44,9 +43,5 @@ class ErrorStripeRangeMarkerTree extends RangeMarkerTree<ErrorStripeMarkerImpl>
|
||||
myLayer = layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Getter<ErrorStripeMarkerImpl> createGetter(@NotNull ErrorStripeMarkerImpl interval) {
|
||||
return interval;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import com.intellij.util.DocumentUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class FoldRegionImpl extends RangeMarkerWithGetterImpl implements FoldRegion {
|
||||
public class FoldRegionImpl extends RangeMarkerImpl implements FoldRegion {
|
||||
private static final Key<Boolean> MUTE_INNER_HIGHLIGHTERS = Key.create("mute.inner.highlighters");
|
||||
private static final Key<Boolean> SHOW_GUTTER_MARK_FOR_SINGLE_LINE = Key.create("show.gutter.mark.for.single.line");
|
||||
|
||||
@@ -30,7 +30,7 @@ public class FoldRegionImpl extends RangeMarkerWithGetterImpl implements FoldReg
|
||||
@NotNull String placeholder,
|
||||
@Nullable FoldingGroup group,
|
||||
boolean shouldNeverExpand) {
|
||||
super(editor.getDocument(), startOffset, endOffset,false);
|
||||
super(editor.getDocument(), startOffset, endOffset,false, true);
|
||||
myGroup = group;
|
||||
myShouldNeverExpand = shouldNeverExpand;
|
||||
myIsExpanded = true;
|
||||
|
||||
@@ -716,14 +716,14 @@ public class FoldingModelImpl extends InlayModel.SimpleAdapter
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Node<FoldRegionImpl> createNewNode(@NotNull FoldRegionImpl key,
|
||||
protected RMNode<FoldRegionImpl> createNewNode(@NotNull FoldRegionImpl key,
|
||||
int start,
|
||||
int end,
|
||||
boolean greedyToLeft,
|
||||
boolean greedyToRight,
|
||||
boolean stickingToRight,
|
||||
int layer) {
|
||||
return new Node<FoldRegionImpl>(this, key, start, end, greedyToLeft, greedyToRight, stickingToRight) {
|
||||
return new RMNode<FoldRegionImpl>(this, key, start, end, greedyToLeft, greedyToRight, stickingToRight) {
|
||||
@Override
|
||||
void onRemoved() {
|
||||
for (Getter<FoldRegionImpl> getter : intervals) {
|
||||
@@ -766,7 +766,7 @@ public class FoldingModelImpl extends InlayModel.SimpleAdapter
|
||||
if (oldLength > 0 /* document change can cause regions to become equal*/) {
|
||||
for (Object o : affected) {
|
||||
//noinspection unchecked
|
||||
Node<FoldRegionImpl> node = (Node<FoldRegionImpl>)o;
|
||||
RMNode<FoldRegionImpl> node = (RMNode<FoldRegionImpl>)o;
|
||||
FoldRegionImpl region = getRegion(node);
|
||||
// region with the largest metric value is kept when several regions become identical after document change
|
||||
// we want the largest collapsed region to survive
|
||||
|
||||
+3
-30
@@ -2,46 +2,19 @@
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* {@link RangeMarkerTree} with intervals which are not collected when no one holds a reference to them.
|
||||
*
|
||||
* @see RangeMarkerWithGetterImpl
|
||||
*/
|
||||
class HardReferencingRangeMarkerTree<T extends RangeMarkerWithGetterImpl> extends RangeMarkerTree<T> {
|
||||
class HardReferencingRangeMarkerTree<T extends RangeMarkerImpl> extends RangeMarkerTree<T> {
|
||||
HardReferencingRangeMarkerTree(@NotNull Document document) {
|
||||
super(document);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Node<T> createNewNode(@NotNull T key,
|
||||
int start,
|
||||
int end,
|
||||
boolean greedyToLeft,
|
||||
boolean greedyToRight,
|
||||
boolean stickingToRight,
|
||||
int layer) {
|
||||
return new Node<>(this, key, start, end, greedyToLeft, greedyToRight, stickingToRight);
|
||||
protected boolean keepIntervalsOnWeakReferences() {
|
||||
return false;
|
||||
}
|
||||
|
||||
static class Node<T extends RangeMarkerWithGetterImpl> extends RMNode<T> {
|
||||
Node(@NotNull RangeMarkerTree<T> rangeMarkerTree,
|
||||
@NotNull T key,
|
||||
int start,
|
||||
int end,
|
||||
boolean greedyToLeft,
|
||||
boolean greedyToRight,
|
||||
boolean stickingToRight) {
|
||||
super(rangeMarkerTree, key, start, end, greedyToLeft, greedyToRight, stickingToRight);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Getter<T> createGetter(@NotNull T interval) {
|
||||
//noinspection unchecked
|
||||
return (Getter<T>) interval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Objects;
|
||||
|
||||
abstract class InlayImpl<R extends EditorCustomElementRenderer, T extends InlayImpl<?, ?>> extends RangeMarkerWithGetterImpl implements Inlay<R> {
|
||||
abstract class InlayImpl<R extends EditorCustomElementRenderer, T extends InlayImpl<?, ?>> extends RangeMarkerImpl implements Inlay<R> {
|
||||
static final Key<Integer> OFFSET_BEFORE_DISPOSAL = Key.create("inlay.offset.before.disposal");
|
||||
|
||||
@NotNull
|
||||
@@ -28,7 +28,7 @@ abstract class InlayImpl<R extends EditorCustomElementRenderer, T extends InlayI
|
||||
|
||||
@SuppressWarnings("AbstractMethodCallInConstructor")
|
||||
InlayImpl(@NotNull EditorImpl editor, int offset, boolean relatesToPrecedingText, @NotNull R renderer) {
|
||||
super(editor.getDocument(), offset, offset, false);
|
||||
super(editor.getDocument(), offset, offset, false, true);
|
||||
myEditor = editor;
|
||||
myRelatedToPrecedingText = relatesToPrecedingText;
|
||||
myRenderer = renderer;
|
||||
|
||||
@@ -517,9 +517,9 @@ public final class InlayModelImpl implements InlayModel, PrioritizedDocumentList
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Node<InlineInlayImpl<?>> createNewNode(@NotNull InlineInlayImpl key, int start, int end,
|
||||
protected RMNode<InlineInlayImpl<?>> createNewNode(@NotNull InlineInlayImpl key, int start, int end,
|
||||
boolean greedyToLeft, boolean greedyToRight, boolean stickingToRight, int layer) {
|
||||
return new Node<InlineInlayImpl<?>>(this, key, start, end, greedyToLeft, greedyToRight, stickingToRight) {
|
||||
return new RMNode<InlineInlayImpl<?>>(this, key, start, end, greedyToLeft, greedyToRight, stickingToRight) {
|
||||
@Override
|
||||
void addIntervalsFrom(@NotNull IntervalNode<InlineInlayImpl<?>> otherNode) {
|
||||
super.addIntervalsFrom(otherNode);
|
||||
|
||||
+9
-9
@@ -13,7 +13,7 @@ import java.util.function.IntSupplier;
|
||||
* Only 'non-greedy' markers with zero length are supported (for such markers start offset is always equal to end offset).
|
||||
* Not thread safe - cannot be used from multiple threads simultaneously.
|
||||
*/
|
||||
class MarkerTreeWithPartialSums<T extends RangeMarkerWithGetterImpl & IntSupplier> extends HardReferencingRangeMarkerTree<T> {
|
||||
class MarkerTreeWithPartialSums<T extends RangeMarkerImpl & IntSupplier> extends HardReferencingRangeMarkerTree<T> {
|
||||
MarkerTreeWithPartialSums(@NotNull Document document) {
|
||||
super(document);
|
||||
}
|
||||
@@ -53,13 +53,13 @@ class MarkerTreeWithPartialSums<T extends RangeMarkerWithGetterImpl & IntSupplie
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected HardReferencingRangeMarkerTree.Node<T> createNewNode(@NotNull T key,
|
||||
int start,
|
||||
int end,
|
||||
boolean greedyToLeft,
|
||||
boolean greedyToRight,
|
||||
boolean stickingToRight,
|
||||
int layer) {
|
||||
protected RMNode<T> createNewNode(@NotNull T key,
|
||||
int start,
|
||||
int end,
|
||||
boolean greedyToLeft,
|
||||
boolean greedyToRight,
|
||||
boolean stickingToRight,
|
||||
int layer) {
|
||||
assert start == end;
|
||||
assert !greedyToLeft;
|
||||
assert !greedyToRight;
|
||||
@@ -72,7 +72,7 @@ class MarkerTreeWithPartialSums<T extends RangeMarkerWithGetterImpl & IntSupplie
|
||||
((Node<T>)node).recalculateSubTreeSum();
|
||||
}
|
||||
|
||||
static class Node<T extends RangeMarkerWithGetterImpl & IntSupplier> extends HardReferencingRangeMarkerTree.Node<T> {
|
||||
static class Node<T extends RangeMarkerImpl & IntSupplier> extends RMNode<T> {
|
||||
private int subtreeSum;
|
||||
|
||||
Node(@NotNull RangeMarkerTree<T> rangeMarkerTree,
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @see HardReferencingRangeMarkerTree
|
||||
*/
|
||||
class RangeMarkerWithGetterImpl extends RangeMarkerImpl implements Getter<RangeMarkerWithGetterImpl> {
|
||||
RangeMarkerWithGetterImpl(@NotNull DocumentEx document, int start, int end, boolean register) {
|
||||
super(document, start, end, register, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final RangeMarkerWithGetterImpl get() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -187,7 +187,7 @@ public class MarkerTreeWithPartialSumsTest extends AbstractEditorTest {
|
||||
return result;
|
||||
}
|
||||
|
||||
private class MyRange extends RangeMarkerWithGetterImpl implements IntSupplier {
|
||||
private class MyRange extends RangeMarkerImpl implements IntSupplier {
|
||||
private int myValue;
|
||||
|
||||
MyRange(int offset, int value) {
|
||||
@@ -195,7 +195,7 @@ public class MarkerTreeWithPartialSumsTest extends AbstractEditorTest {
|
||||
}
|
||||
|
||||
MyRange(int offset, int value, boolean stickToRight) {
|
||||
super(myDocument, offset, offset, false);
|
||||
super(myDocument, offset, offset, false, true);
|
||||
myValue = value;
|
||||
myTree.addInterval(this, offset, offset, false, false, stickToRight, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user