From 2f78f91ec3336a7759d6ea49e1c7289b0360f396 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Tue, 27 Oct 2009 20:46:13 +0300 Subject: [PATCH] A few contention optimizations --- .../src/com/intellij/lexer/JavaLexer.java | 27 +++++- .../psi/controlFlow/ControlFlowFactory.java | 12 ++- .../intellij/psi/impl/PsiNameHelperImpl.java | 88 +++++-------------- .../impl/source/resolve/JavaResolveCache.java | 13 ++- .../ExternalAnnotationsManager.java | 14 ++- 5 files changed, 81 insertions(+), 73 deletions(-) diff --git a/java/java-impl/src/com/intellij/lexer/JavaLexer.java b/java/java-impl/src/com/intellij/lexer/JavaLexer.java index d552ab156ca0..bc69953fcf41 100644 --- a/java/java-impl/src/com/intellij/lexer/JavaLexer.java +++ b/java/java-impl/src/com/intellij/lexer/JavaLexer.java @@ -20,17 +20,17 @@ import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.JavaTokenType; import com.intellij.psi.TokenType; import com.intellij.psi.tree.IElementType; +import gnu.trove.THashSet; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.util.Set; public class JavaLexer extends LexerBase { private JavaLexer(boolean isAssertKeywordEnabled, boolean isJDK15) { - myTable = isAssertKeywordEnabled - ? isJDK15 ? ourTableWithAssertAndJDK15 : ourTableWithAssert - : isJDK15 ? ourTableWithJDK15 : ourTableWithoutAssert; + myTable = getTable(isAssertKeywordEnabled, isJDK15); myFlexlexer = new _JavaLexer(isAssertKeywordEnabled, isJDK15); } @@ -38,6 +38,21 @@ public class JavaLexer extends LexerBase { this(level.hasAssertKeyword(), level.hasEnumKeywordAndAutoboxing()); } + private static HashTable getTable(boolean isAssertKeywordEnabled, boolean isJDK15) { + return isAssertKeywordEnabled + ? isJDK15 ? ourTableWithAssertAndJDK15 : ourTableWithAssert + : isJDK15 ? ourTableWithJDK15 : ourTableWithoutAssert; + } + + private static HashTable getTable(LanguageLevel level) { + return getTable(level.hasAssertKeyword(), level.hasEnumKeywordAndAutoboxing()); + } + + + public static boolean isKeyword(String id, LanguageLevel level) { + return getTable(level).contains(id); + } + private CharSequence myBuffer; private int myBufferIndex; private int myBufferEndOffset; @@ -54,6 +69,7 @@ public class JavaLexer extends LexerBase { private final char[][] myTable = new char[NUM_ENTRIES][]; private final IElementType[] myKeywords = new IElementType[NUM_ENTRIES]; + private final Set myKeywordsInSet = new THashSet(); private void add(String s, IElementType tokenType) { char[] chars = s.toCharArray(); @@ -66,6 +82,11 @@ public class JavaLexer extends LexerBase { myTable[modHashCode] = chars; myKeywords[modHashCode] = tokenType; + myKeywordsInSet.add(s); + } + + public boolean contains(String s) { + return myKeywordsInSet.contains(s); } private boolean contains(int hashCode, final CharSequence buffer, int offset) { diff --git a/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java b/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java index a961ffb2063e..5de1c60db95c 100644 --- a/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java +++ b/java/java-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java @@ -26,9 +26,11 @@ package com.intellij.psi.controlFlow; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.NotNullLazyKey; import com.intellij.psi.PsiElement; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.util.ConcurrencyUtil; +import com.intellij.util.NotNullFunction; import com.intellij.util.containers.ConcurrentWeakHashMap; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -42,10 +44,18 @@ public class ControlFlowFactory { // psiElements hold weakly, controlFlows softly private final ConcurrentMap>> cachedFlows = new ConcurrentWeakHashMap>>(); + private static final NotNullLazyKey INSTANCE_KEY = NotNullLazyKey.create("ControlFlowFactory.Instance.Cache", new NotNullFunction() { + @NotNull + public ControlFlowFactory fun(final Project project) { + return ServiceManager.getService(project, ControlFlowFactory.class); + } + }); + public static ControlFlowFactory getInstance(Project project) { - return ServiceManager.getService(project, ControlFlowFactory.class); + return INSTANCE_KEY.getValue(project); } + public ControlFlowFactory(PsiManagerEx psiManager) { psiManager.registerRunnableToRunOnChange(new Runnable(){ public void run() { diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiNameHelperImpl.java b/java/java-impl/src/com/intellij/psi/impl/PsiNameHelperImpl.java index 357d6c2fdd06..eb26d2c76837 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiNameHelperImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiNameHelperImpl.java @@ -1,94 +1,52 @@ - /* - * Copyright 2000-2009 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. - */ +* Copyright 2000-2009 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 com.intellij.psi.impl; import com.intellij.lexer.JavaLexer; -import com.intellij.lexer.Lexer; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.JavaTokenType; import com.intellij.psi.PsiNameHelper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class PsiNameHelperImpl extends PsiNameHelper{ - private final JavaPsiFacade myManager; - private Lexer myLexer; - private LanguageLevel myLastLanguageLevel; - private final Object LOCK = new Object(); +public class PsiNameHelperImpl extends PsiNameHelper { + private final LanguageLevelProjectExtension myLanguageLevelExtension; public PsiNameHelperImpl(JavaPsiFacade manager) { - myManager = manager; - myLastLanguageLevel = LanguageLevelProjectExtension.getInstance(manager.getProject()).getLanguageLevel(); - myLexer = new JavaLexer(myLastLanguageLevel); - } - - private void updateLexer(LanguageLevel languageLevel){ - if (!myLastLanguageLevel.equals(languageLevel)){ - myLastLanguageLevel = languageLevel; - myLexer = new JavaLexer(myLastLanguageLevel); - } + myLanguageLevelExtension = LanguageLevelProjectExtension.getInstance(manager.getProject()); } public boolean isIdentifier(@Nullable String text) { - ApplicationManager.getApplication().assertReadAccessAllowed(); - if (text == null) return false; - - synchronized (LOCK) { - updateLexer(LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel()); - myLexer.start(text); - if (myLexer.getTokenType() != JavaTokenType.IDENTIFIER) return false; - myLexer.advance(); - return myLexer.getTokenType() == null; - } + return isIdentifier(text, myLanguageLevelExtension.getLanguageLevel()); } public boolean isIdentifier(@Nullable String text, @NotNull LanguageLevel languageLevel) { - ApplicationManager.getApplication().assertReadAccessAllowed(); - if (text == null) return false; - - synchronized (LOCK) { - updateLexer(languageLevel); - myLexer.start(text); - if (myLexer.getTokenType() != JavaTokenType.IDENTIFIER) return false; - myLexer.advance(); - return myLexer.getTokenType() == null; - } + return text != null && StringUtil.isJavaIdentifier(text) && !JavaLexer.isKeyword(text, languageLevel); } public boolean isKeyword(@Nullable String text) { - ApplicationManager.getApplication().assertReadAccessAllowed(); - if (text == null) return false; - - synchronized (LOCK) { - updateLexer(LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel()); - myLexer.start(text); - if (myLexer.getTokenType() == null || !JavaTokenType.KEYWORD_BIT_SET.contains(myLexer.getTokenType())) return false; - myLexer.advance(); - return myLexer.getTokenType() == null; - } + return text != null && JavaLexer.isKeyword(text, myLanguageLevelExtension.getLanguageLevel()); } - public boolean isQualifiedName(@Nullable String text){ + public boolean isQualifiedName(@Nullable String text) { if (text == null) return false; int index = 0; - while(true){ + while (true) { int index1 = text.indexOf('.', index); if (index1 < 0) index1 = text.length(); if (!isIdentifier(text.substring(index, index1))) return false; diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java index ca5a5503ea2d..107b8f4ec629 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java @@ -23,6 +23,7 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.NotNullLazyKey; import com.intellij.psi.PsiEllipsisType; import com.intellij.psi.PsiExpression; import com.intellij.psi.PsiType; @@ -30,6 +31,7 @@ import com.intellij.psi.PsiVariable; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.Function; +import com.intellij.util.NotNullFunction; import com.intellij.util.containers.ConcurrentWeakHashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -42,8 +44,15 @@ import java.util.concurrent.ConcurrentMap; public class JavaResolveCache { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.resolve.JavaResolveCache"); + private static final NotNullLazyKey INSTANCE_KEY = NotNullLazyKey.create("JavaResolveCache.Instance.Cache", new NotNullFunction() { + @NotNull + public JavaResolveCache fun(final Project project) { + return ServiceManager.getService(project, JavaResolveCache.class); + } + }); + public static JavaResolveCache getInstance(Project project) { - return ServiceManager.getService(project, JavaResolveCache.class); + return INSTANCE_KEY.getValue(project); } private final ConcurrentMap myCalculatedTypes = new ConcurrentWeakHashMap(); @@ -114,4 +123,4 @@ public class JavaResolveCache { public interface ConstValueComputer{ Object execute(PsiVariable variable, Set visitedVars); } -} \ No newline at end of file +} diff --git a/java/openapi/src/com/intellij/codeInsight/ExternalAnnotationsManager.java b/java/openapi/src/com/intellij/codeInsight/ExternalAnnotationsManager.java index 143234f90f86..cb869c71871f 100644 --- a/java/openapi/src/com/intellij/codeInsight/ExternalAnnotationsManager.java +++ b/java/openapi/src/com/intellij/codeInsight/ExternalAnnotationsManager.java @@ -22,11 +22,14 @@ package com.intellij.codeInsight; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.NotNullLazyKey; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiModifierListOwner; +import com.intellij.util.NotNullFunction; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public abstract class ExternalAnnotationsManager { @@ -38,8 +41,15 @@ public abstract class ExternalAnnotationsManager { NOWHERE } + private static final NotNullLazyKey INSTANCE_KEY = NotNullLazyKey.create("ExternalAnnotationsManager.Instance.Cache", new NotNullFunction() { + @NotNull + public ExternalAnnotationsManager fun(final Project project) { + return ServiceManager.getService(project, ExternalAnnotationsManager.class); + } + }); + public static ExternalAnnotationsManager getInstance(Project project) { - return ServiceManager.getService(project, ExternalAnnotationsManager.class); + return INSTANCE_KEY.getValue(project); } @Nullable @@ -54,4 +64,4 @@ public abstract class ExternalAnnotationsManager { public abstract AnnotationPlace chooseAnnotationsPlace(final PsiElement element); -} \ No newline at end of file +}