Skip to content

Commit 2090723

Browse files
authored
Fix reemerged compiler concurrency issues (#3143)
#3034 broke the fix for #1599 by changing packages
1 parent b26c79c commit 2090723

File tree

3 files changed

+92
-54
lines changed

3 files changed

+92
-54
lines changed

subprojects/analysis-kotlin-descriptors/compiler/api/compiler.api

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,27 @@ public final class org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl
100100
public final fun getContext ()Lorg/jetbrains/dokka/plugability/DokkaContext;
101101
}
102102

103+
public final class org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl : com/intellij/core/CoreJavaFileManager, org/jetbrains/kotlin/resolve/jvm/KotlinCliJavaFileManager {
104+
public static final field Companion Lorg/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl$Companion;
105+
public fun <init> (Lcom/intellij/psi/PsiManager;)V
106+
public fun findClass (Ljava/lang/String;Lcom/intellij/psi/search/GlobalSearchScope;)Lcom/intellij/psi/PsiClass;
107+
public fun findClass (Lorg/jetbrains/kotlin/load/java/JavaClassFinder$Request;Lcom/intellij/psi/search/GlobalSearchScope;)Lorg/jetbrains/kotlin/load/java/structure/JavaClass;
108+
public final fun findClass (Lorg/jetbrains/kotlin/name/ClassId;Lcom/intellij/psi/search/GlobalSearchScope;)Lorg/jetbrains/kotlin/load/java/structure/JavaClass;
109+
public fun findClasses (Ljava/lang/String;Lcom/intellij/psi/search/GlobalSearchScope;)[Lcom/intellij/psi/PsiClass;
110+
public fun findModules (Ljava/lang/String;Lcom/intellij/psi/search/GlobalSearchScope;)Ljava/util/Collection;
111+
public fun findPackage (Ljava/lang/String;)Lcom/intellij/psi/PsiPackage;
112+
public fun getNonTrivialPackagePrefixes ()Ljava/util/Collection;
113+
public final fun initialize (Lorg/jetbrains/kotlin/cli/jvm/index/JvmDependenciesIndex;Ljava/util/List;Lorg/jetbrains/kotlin/cli/jvm/index/SingleJavaFileRootsIndex;Z)V
114+
public fun knownClassNamesInPackage (Lorg/jetbrains/kotlin/name/FqName;)Ljava/util/Set;
115+
}
116+
117+
public final class org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl$Companion {
118+
}
119+
120+
public final class org/jetbrains/kotlin/cli/jvm/index/JvmDependenciesIndexImpl : org/jetbrains/kotlin/cli/jvm/index/JvmDependenciesIndex {
121+
public fun <init> (Ljava/util/List;)V
122+
public fun findClass (Lorg/jetbrains/kotlin/name/ClassId;Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
123+
public fun getIndexedRoots ()Lkotlin/sequences/Sequence;
124+
public fun traverseDirectoriesInPackage (Lorg/jetbrains/kotlin/name/FqName;Ljava/util/Set;Lkotlin/jvm/functions/Function2;)V
125+
}
126+

subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/JvmDependenciesIndexImpl.kt

Lines changed: 56 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,35 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration
17+
/**
18+
* DO NOT MOVE IT
19+
* This is a hack for https://github.com/Kotlin/dokka/issues/1599
20+
*
21+
* Copy-pasted from 1.9.20-Beta-1
22+
* Can be removed for Kotlin compiler 1.9.20 and later
23+
*
24+
* It makes this class threadsafe for Dokka
25+
*/
26+
@file:Suppress("PackageDirectoryMismatch")
27+
package org.jetbrains.kotlin.cli.jvm.index
1828

1929
import com.intellij.ide.highlighter.JavaClassFileType
2030
import com.intellij.ide.highlighter.JavaFileType
2131
import com.intellij.openapi.vfs.VfsUtilCore
2232
import com.intellij.openapi.vfs.VirtualFile
2333
import gnu.trove.THashMap
24-
import it.unimi.dsi.fastutil.ints.IntArrayList
25-
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
26-
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
2734
import org.jetbrains.kotlin.name.ClassId
2835
import org.jetbrains.kotlin.name.FqName
36+
import java.util.*
37+
import java.util.concurrent.locks.ReentrantLock
38+
import kotlin.concurrent.withLock
2939

3040
// speeds up finding files/classes in classpath/java source roots
31-
// NOT THREADSAFE, needs to be adapted/removed if we want compiler to be multithreaded
41+
// TODO: KT-58327 needs to be adapted/removed if we want compiler to be multithreaded
3242
// the main idea of this class is for each package to store roots which contains it to avoid excessive file system traversal
33-
internal class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependenciesIndex {
43+
class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependenciesIndex {
44+
private val lock = ReentrantLock()
45+
3446
//these fields are computed based on _roots passed to constructor which are filled in later
3547
private val roots: List<JavaRoot> by lazy { _roots.toList() }
3648

@@ -46,7 +58,8 @@ internal class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependencie
4658
// indices of roots that are known to contain this package
4759
// if this list contains [1, 3, 5] then roots with indices 1, 3 and 5 are known to contain this package, 2 and 4 are known not to (no information about roots 6 or higher)
4860
// if this list contains maxIndex that means that all roots containing this package are known
49-
val rootIndices = IntArrayList(2)
61+
@Suppress("DEPRECATION") // TODO: fix deprecation
62+
val rootIndices = com.intellij.util.containers.IntArrayList(2)
5063
}
5164

5265
// root "Cache" object corresponds to DefaultPackage which exists in every root. Roots with non-default fqname are also listed here but
@@ -55,7 +68,7 @@ internal class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependencie
5568
Cache().apply {
5669
roots.indices.forEach(rootIndices::add)
5770
rootIndices.add(maxIndex)
58-
rootIndices.trimToSize(0)
71+
rootIndices.trimToSize()
5972
}
6073
}
6174

@@ -74,8 +87,10 @@ internal class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependencie
7487
acceptedRootTypes: Set<JavaRoot.RootType>,
7588
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
7689
) {
77-
search(TraverseRequest(packageFqName, acceptedRootTypes)) { dir, rootType ->
78-
if (continueSearch(dir, rootType)) null else Unit
90+
lock.withLock {
91+
search(TraverseRequest(packageFqName, acceptedRootTypes)) { dir, rootType ->
92+
if (continueSearch(dir, rootType)) null else Unit
93+
}
7994
}
8095
}
8196

@@ -85,34 +100,37 @@ internal class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependencie
85100
acceptedRootTypes: Set<JavaRoot.RootType>,
86101
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
87102
): T? {
88-
// make a decision based on information saved from last class search
89-
if (lastClassSearch?.first?.classId != classId) {
90-
return search(FindClassRequest(classId, acceptedRootTypes), findClassGivenDirectory)
91-
}
103+
lock.withLock {
104+
// TODO: KT-58327 probably should be changed to thread local to fix fast-path
105+
// make a decision based on information saved from last class search
106+
if (lastClassSearch?.first?.classId != classId) {
107+
return search(FindClassRequest(classId, acceptedRootTypes), findClassGivenDirectory)
108+
}
92109

93-
val (cachedRequest, cachedResult) = lastClassSearch!!
94-
return when (cachedResult) {
95-
is SearchResult.NotFound -> {
96-
val limitedRootTypes = acceptedRootTypes - cachedRequest.acceptedRootTypes
97-
if (limitedRootTypes.isEmpty()) {
98-
null
99-
} else {
100-
search(FindClassRequest(classId, limitedRootTypes), findClassGivenDirectory)
110+
val (cachedRequest, cachedResult) = lastClassSearch!!
111+
return when (cachedResult) {
112+
is SearchResult.NotFound -> {
113+
val limitedRootTypes = acceptedRootTypes - cachedRequest.acceptedRootTypes
114+
if (limitedRootTypes.isEmpty()) {
115+
null
116+
} else {
117+
search(FindClassRequest(classId, limitedRootTypes), findClassGivenDirectory)
118+
}
101119
}
102-
}
103-
is SearchResult.Found -> {
104-
if (cachedRequest.acceptedRootTypes == acceptedRootTypes) {
105-
findClassGivenDirectory(cachedResult.packageDirectory, cachedResult.root.type)
106-
} else {
107-
search(FindClassRequest(classId, acceptedRootTypes), findClassGivenDirectory)
120+
is SearchResult.Found -> {
121+
if (cachedRequest.acceptedRootTypes == acceptedRootTypes) {
122+
findClassGivenDirectory(cachedResult.packageDirectory, cachedResult.root.type)
123+
} else {
124+
search(FindClassRequest(classId, acceptedRootTypes), findClassGivenDirectory)
125+
}
108126
}
109127
}
110128
}
111129
}
112130

113131
private fun <T : Any> search(request: SearchRequest, handler: (VirtualFile, JavaRoot.RootType) -> T?): T? {
114132
// a list of package sub names, ["org", "jb", "kotlin"]
115-
val packagesPath = request.packageFqName.pathSegments().map { it.identifier }
133+
val packagesPath = request.packageFqName.pathSegments().map { it.identifierOrNullIfSpecial ?: return null }
116134
// a list of caches corresponding to packages, [default, "org", "org.jb", "org.jb.kotlin"]
117135
val caches = cachesPath(packagesPath)
118136

@@ -122,12 +140,11 @@ internal class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependencie
122140
// NOTE: indices manipulation instead of using caches.reversed() is here for performance reasons
123141
for (cacheIndex in caches.lastIndex downTo 0) {
124142
val cacheRootIndices = caches[cacheIndex].rootIndices
125-
for (i in 0 until cacheRootIndices.size) {
126-
val rootIndex = cacheRootIndices.getInt(i)
143+
for (i in 0 until cacheRootIndices.size()) {
144+
val rootIndex = cacheRootIndices[i]
127145
if (rootIndex <= processedRootsUpTo) continue // roots with those indices have been processed by now
128146

129-
val directoryInRoot =
130-
travelPath(rootIndex, request.packageFqName, packagesPath, cacheIndex, caches) ?: continue
147+
val directoryInRoot = travelPath(rootIndex, request.packageFqName, packagesPath, cacheIndex, caches) ?: continue
131148
val root = roots[rootIndex]
132149
if (root.type in request.acceptedRootTypes) {
133150
val result = handler(directoryInRoot, root.type)
@@ -139,12 +156,7 @@ internal class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependencie
139156
}
140157
}
141158
}
142-
processedRootsUpTo =
143-
if (cacheRootIndices.isEmpty()) {
144-
processedRootsUpTo
145-
} else {
146-
cacheRootIndices.getInt(cacheRootIndices.size - 1)
147-
}
159+
processedRootsUpTo = if (cacheRootIndices.isEmpty) processedRootsUpTo else cacheRootIndices[cacheRootIndices.size() - 1]
148160
}
149161

150162
if (request is FindClassRequest) {
@@ -166,15 +178,13 @@ internal class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependencie
166178
for (i in (fillCachesAfter + 1) until cachesPath.size) {
167179
// we all know roots that contain this package by now
168180
cachesPath[i].rootIndices.add(maxIndex)
169-
cachesPath[i].rootIndices.trimToSize(0)
181+
cachesPath[i].rootIndices.trimToSize()
170182
}
171183
return null
172184
}
173185

174-
return synchronized(packageCache) {
175-
packageCache[rootIndex].getOrPut(packageFqName.asString()) {
176-
doTravelPath(rootIndex, packagesPath, fillCachesAfter, cachesPath)
177-
}
186+
return packageCache[rootIndex].getOrPut(packageFqName.asString()) {
187+
doTravelPath(rootIndex, packagesPath, fillCachesAfter, cachesPath)
178188
}
179189
}
180190

@@ -236,12 +246,7 @@ internal class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependencie
236246
return caches
237247
}
238248

239-
private fun <E> MutableList<E>.trimToSize(newSize: Int) {
240-
subList(newSize, size).clear()
241-
}
242-
243-
private data class FindClassRequest(val classId: ClassId, override val acceptedRootTypes: Set<JavaRoot.RootType>) :
244-
SearchRequest {
249+
private data class FindClassRequest(val classId: ClassId, override val acceptedRootTypes: Set<JavaRoot.RootType>) : SearchRequest {
245250
override val packageFqName: FqName
246251
get() = classId.packageFqName
247252
}
@@ -261,4 +266,4 @@ internal class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependencie
261266

262267
object NotFound : SearchResult()
263268
}
264-
}
269+
}

subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/KotlinCliJavaFileManagerImpl.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,17 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration
17+
/**
18+
* DO NOT MOVE IT
19+
* This is a hack for https://github.com/Kotlin/dokka/issues/1599
20+
*
21+
* Copy-pasted from Kotlin compiler
22+
*
23+
* It makes this class threadsafe (`topLevelClassesCache` and `binaryCache`) for Dokka
24+
*
25+
*/
26+
@file:Suppress("PackageDirectoryMismatch")
27+
package org.jetbrains.kotlin.cli.jvm.compiler
1828

1929
import com.intellij.core.CoreJavaFileManager
2030
import com.intellij.openapi.diagnostic.Logger
@@ -25,7 +35,6 @@ import com.intellij.psi.impl.file.PsiPackageImpl
2535
import com.intellij.psi.search.GlobalSearchScope
2636
import gnu.trove.THashMap
2737
import gnu.trove.THashSet
28-
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
2938
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
3039
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
3140
import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex
@@ -44,7 +53,7 @@ import org.jetbrains.kotlin.util.PerformanceCounter
4453
// TODO: do not inherit from CoreJavaFileManager to avoid accidental usage of its methods which do not use caches/indices
4554
// Currently, the only relevant usage of this class as CoreJavaFileManager is at CoreJavaDirectoryService.getPackage,
4655
// which is indirectly invoked from PsiPackage.getSubPackages
47-
internal class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager {
56+
class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager {
4857
private val perfCounter = PerformanceCounter.create("Find Java class")
4958
private lateinit var index: JvmDependenciesIndex
5059
private lateinit var singleJavaFileRootsIndex: SingleJavaFileRootsIndex

0 commit comments

Comments
 (0)