avoid global lock accessing CharTableImpl.STATIC_ENTRIES because it caused a lot of contention sometimes (see https://jetbrains.team/p/ij/reviews/94493, GoParserPerformanceTest.testLeafInternContention), make STATIC_ENTRIES immutable for that

GitOrigin-RevId: ad29ceb30686c44c4b82f664e6143ebf9611bc33
This commit is contained in:
Alexey Kudravtsev
2022-08-24 15:03:42 +00:00
committed by intellij-monorepo-bot
parent 107d5b241f
commit 232e086418
3 changed files with 82 additions and 149 deletions
@@ -1,7 +1,6 @@
// Copyright 2000-2020 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.psi.impl.java.stubs.impl;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
@@ -23,17 +22,10 @@ import org.jetbrains.annotations.NotNull;
public class PsiAnnotationStubImpl extends StubBase<PsiAnnotation> implements PsiAnnotationStub {
private static final Logger LOG = Logger.getInstance(PsiAnnotationStubImpl.class);
static {
CharTableImpl.addStringsFromClassToStatics(AnnotationUtil.class);
CharTableImpl.staticIntern("@NotNull");
CharTableImpl.staticIntern("@Nullable");
CharTableImpl.staticIntern("@Override");
}
private final String myText;
private SoftReference<PsiAnnotation> myParsedFromRepository;
public PsiAnnotationStubImpl(StubElement parent, @NotNull String text) {
public PsiAnnotationStubImpl(StubElement<?> parent, @NotNull String text) {
super(parent, JavaStubElementTypes.ANNOTATION);
CharSequence interned = CharTableImpl.getStaticInterned(text);
myText = interned == null ? text : interned.toString();
@@ -15,18 +15,14 @@
*/
package com.intellij.psi.impl.source.tree.java;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiJavaToken;
import com.intellij.psi.PsiKeyword;
import com.intellij.psi.impl.source.CharTableImpl;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
public class PsiKeywordImpl extends LeafPsiElement implements PsiKeyword, PsiJavaToken {
public PsiKeywordImpl(@NotNull IElementType type, CharSequence text) {
super(type, text);
@@ -51,10 +47,4 @@ public class PsiKeywordImpl extends LeafPsiElement implements PsiKeyword, PsiJav
public String toString(){
return "PsiKeyword:" + getText();
}
static {
for(Field field: PsiKeyword.class.getFields()) {
CharTableImpl.staticIntern(StringUtil.toLowerCase(field.getName()));
}
}
}
@@ -2,17 +2,12 @@
package com.intellij.psi.impl.source;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.CommonClassNames;
import com.intellij.util.ArrayUtil;
import com.intellij.util.CharTable;
import com.intellij.util.ReflectionUtil;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public final class CharTableImpl implements CharTable {
private static final int INTERN_THRESHOLD = 40; // 40 or more characters long tokens won't be interned.
@@ -28,11 +23,14 @@ public final class CharTableImpl implements CharTable {
@NotNull
private CharSequence doIntern(@NotNull CharSequence text, int startOffset, int endOffset) {
int hashCode = subSequenceHashCode(text, startOffset, endOffset);
CharSequence interned;
synchronized (STATIC_ENTRIES) {
interned = STATIC_ENTRIES.getSubSequenceWithHashCode(hashCode, text, startOffset, endOffset);
int hashCode;
if (startOffset == 0 && endOffset == text.length()) {
hashCode = StringUtil.stringHashCode(text);
}
else {
hashCode = StringUtil.stringHashCode(text, startOffset, endOffset);
}
CharSequence interned = STATIC_ENTRIES.getSubSequenceWithHashCode(hashCode, text, startOffset, endOffset);
if (interned != null) {
return interned;
}
@@ -50,12 +48,8 @@ public final class CharTableImpl implements CharTable {
@NotNull
@Override
public CharSequence intern(@NotNull CharSequence baseText, int startOffset, int endOffset) {
CharSequence result;
if (endOffset - startOffset == baseText.length()) result = intern(baseText);
else if (endOffset - startOffset > INTERN_THRESHOLD) result = substring(baseText, startOffset, endOffset);
else result = doIntern(baseText, startOffset, endOffset);
return result;
return endOffset - startOffset > INTERN_THRESHOLD ? substring(baseText, startOffset, endOffset)
: doIntern(baseText, startOffset, endOffset);
}
@NotNull
@@ -71,87 +65,81 @@ public final class CharTableImpl implements CharTable {
return STATIC_ENTRIES.get(text);
}
public static void staticIntern(@NotNull String text) {
synchronized(STATIC_ENTRIES) {
STATIC_ENTRIES.add(text);
}
}
@NotNull
private static StringHashToCharSequencesMap newStaticSet() {
StringHashToCharSequencesMap r = new StringHashToCharSequencesMap(10, 0.9f);
r.add("==" );
r.add("!=" );
r.add("||" );
r.add("++" );
r.add("--" );
r.add("==");
r.add("!=");
r.add("||");
r.add("++");
r.add("--");
r.add("<" );
r.add("<=" );
r.add("<<=" );
r.add("<<" );
r.add(">" );
r.add("&" );
r.add("&&" );
r.add("<");
r.add("<=");
r.add("<<=");
r.add("<<");
r.add(">");
r.add("&");
r.add("&&");
r.add("+=" );
r.add("-=" );
r.add("*=" );
r.add("/=" );
r.add("&=" );
r.add("|=" );
r.add("^=" );
r.add("%=" );
r.add("+=");
r.add("-=");
r.add("*=");
r.add("/=");
r.add("&=");
r.add("|=");
r.add("^=");
r.add("%=");
r.add("(" );
r.add(")" );
r.add("{" );
r.add("}" );
r.add("[" );
r.add("]" );
r.add(";" );
r.add("," );
r.add("..." );
r.add("." );
r.add("(");
r.add(")");
r.add("{");
r.add("}");
r.add("[");
r.add("]");
r.add(";");
r.add(",");
r.add("...");
r.add(".");
r.add("=" );
r.add("!" );
r.add("~" );
r.add("?" );
r.add(":" );
r.add("+" );
r.add("-" );
r.add("*" );
r.add("/" );
r.add("|" );
r.add("^" );
r.add("%" );
r.add("@" );
r.add("=");
r.add("!");
r.add("~");
r.add("?");
r.add(":");
r.add("+");
r.add("-");
r.add("*");
r.add("/");
r.add("|");
r.add("^");
r.add("%");
r.add("@");
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add(" " );
r.add("\n" );
r.add("\n " );
r.add("\n " );
r.add("\n " );
r.add("\n " );
r.add("\n " );
r.add("\n " );
r.add("\n " );
r.add("\n " );
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add(" ");
r.add("\n");
r.add("\n ");
r.add("\n ");
r.add("\n ");
r.add("\n ");
r.add("\n ");
r.add("\n ");
r.add("\n ");
r.add("\n ");
r.add("<");
r.add(">");
@@ -159,49 +147,17 @@ public final class CharTableImpl implements CharTable {
r.add("/>");
r.add("\"");
r.add("'");
r.add("<![CDATA[");
r.add("]]>");
r.add("<!--");
r.add("-->");
r.add("<!DOCTYPE");
r.add("SYSTEM");
r.add("PUBLIC");
r.add("<?");
r.add("?>");
r.add("<%");
r.add("%>");
r.add("<%=");
r.add("<%@");
r.add("${");
r.add("");
return r;
}
static {
addStringsFromClassToStatics(CommonClassNames.class);
}
public static void addStringsFromClassToStatics(@NotNull Class<?> aClass) {
for (Field field : aClass.getDeclaredFields()) {
if ((field.getModifiers() & Modifier.STATIC) == 0) continue;
if ((field.getModifiers() & Modifier.PUBLIC) == 0) continue;
if (!String.class.equals(field.getType())) continue;
String typeName = ReflectionUtil.getStaticFieldValue(aClass, String.class, field.getName());
if (typeName != null) {
staticIntern(typeName);
}
}
}
// hashCode -> CharSequence|CharSequence[]
private static final class StringHashToCharSequencesMap extends Int2ObjectOpenHashMap<Object> {
private StringHashToCharSequencesMap(int capacity, float loadFactor) {
super(capacity, loadFactor);
}
private CharSequence get(@NotNull CharSequence sequence, int startOffset, int endOffset) {
return getSubSequenceWithHashCode(subSequenceHashCode(sequence, startOffset, endOffset), sequence, startOffset, endOffset);
}
private CharSequence getSubSequenceWithHashCode(int hashCode, @NotNull CharSequence sequence, int startOffset, int endOffset) {
Object o = get(hashCode);
if (o == null) return null;
@@ -233,12 +189,14 @@ public final class CharTableImpl implements CharTable {
}
private CharSequence get(@NotNull CharSequence sequence) {
return get(sequence, 0, sequence.length());
int endOffset = sequence.length();
int hashCode = StringUtil.stringHashCode(sequence);
return getSubSequenceWithHashCode(hashCode, sequence, 0, endOffset);
}
private void add(@NotNull CharSequence sequence) {
int endOffset = sequence.length();
int hashCode = subSequenceHashCode(sequence, 0, endOffset);
int hashCode = StringUtil.stringHashCode(sequence);
getOrAddSubSequenceWithHashCode(hashCode, sequence, 0, endOffset);
}
@@ -277,11 +235,4 @@ public final class CharTableImpl implements CharTable {
return addedSequence;
}
}
private static int subSequenceHashCode(@NotNull CharSequence sequence, int startOffset, int endOffset) {
if (startOffset == 0 && endOffset == sequence.length()) {
return StringUtil.stringHashCode(sequence);
}
return StringUtil.stringHashCode(sequence, startOffset, endOffset);
}
}