Skip to content

Commit f538af6

Browse files
authored
Workaround for debugger+compiler crash (#3625)
* 'inline' modifier is removed from 'findSegmentInternal'. It previously lead to KT-55983: incorrect SMAP was produced that crashed the debugger consistently * Non-inline functions are non-capturing, thus no additional performance overhead * Method-reference is extracted to a variable in few places as it were crashing JVM compiler with AIOOB consistently
1 parent 54c3108 commit f538af6

File tree

3 files changed

+14
-7
lines changed

3 files changed

+14
-7
lines changed

kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2431,7 +2431,7 @@ internal open class BufferedChannel<E>(
24312431
* segments, updating the counter value in [sendersAndCloseStatus] correspondingly.
24322432
*/
24332433
private fun findSegmentSend(id: Long, startFrom: ChannelSegment<E>): ChannelSegment<E>? {
2434-
return sendSegment.findSegmentAndMoveForward(id, startFrom, ::createSegment).let {
2434+
return sendSegment.findSegmentAndMoveForward(id, startFrom, createSegmentFunction()).let {
24352435
if (it.isClosed) {
24362436
// The required segment has not been found and new segments
24372437
// cannot be added, as the linked listed in already added.
@@ -2486,7 +2486,7 @@ internal open class BufferedChannel<E>(
24862486
* segments, updating the [receivers] counter correspondingly.
24872487
*/
24882488
private fun findSegmentReceive(id: Long, startFrom: ChannelSegment<E>): ChannelSegment<E>? =
2489-
receiveSegment.findSegmentAndMoveForward(id, startFrom, ::createSegment).let {
2489+
receiveSegment.findSegmentAndMoveForward(id, startFrom, createSegmentFunction()).let {
24902490
if (it.isClosed) {
24912491
// The required segment has not been found and new segments
24922492
// cannot be added, as the linked listed in already added.
@@ -2535,7 +2535,7 @@ internal open class BufferedChannel<E>(
25352535
* it always updates the number of completed `expandBuffer()` attempts.
25362536
*/
25372537
private fun findSegmentBufferEnd(id: Long, startFrom: ChannelSegment<E>, currentBufferEndCounter: Long): ChannelSegment<E>? =
2538-
bufferEndSegment.findSegmentAndMoveForward(id, startFrom, ::createSegment).let {
2538+
bufferEndSegment.findSegmentAndMoveForward(id, startFrom, createSegmentFunction()).let {
25392539
if (it.isClosed) {
25402540
// The required segment has not been found and new segments
25412541
// cannot be added, as the linked listed in already added.
@@ -2953,6 +2953,10 @@ internal class ChannelSegment<E>(id: Long, prev: ChannelSegment<E>?, channel: Bu
29532953
onSlotCleaned()
29542954
}
29552955
}
2956+
2957+
// WA for atomicfu + JVM_IR compiler bug that lead to SMAP-related compiler crashes: KT-55983
2958+
internal fun <E> createSegmentFunction(): KFunction2<Long, ChannelSegment<E>, ChannelSegment<E>> = ::createSegment
2959+
29562960
private fun <E> createSegment(id: Long, prev: ChannelSegment<E>) = ChannelSegment(
29572961
id = id,
29582962
prev = prev,

kotlinx-coroutines-core/common/src/internal/ConcurrentLinkedList.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import kotlin.jvm.*
1212
* Returns the first segment `s` with `s.id >= id` or `CLOSED`
1313
* if all the segments in this linked list have lower `id`, and the list is closed for further segment additions.
1414
*/
15-
private inline fun <S : Segment<S>> S.findSegmentInternal(
15+
internal fun <S : Segment<S>> S.findSegmentInternal(
1616
id: Long,
1717
createNewSegment: (id: Long, prev: S) -> S
1818
): SegmentOrClosed<S> {
@@ -62,10 +62,11 @@ internal inline fun <S : Segment<S>> AtomicRef<S>.moveForward(to: S): Boolean =
6262
* Returns the segment `s` with `s.id >= id` or `CLOSED` if all the segments in this linked list have lower `id`,
6363
* and the list is closed.
6464
*/
65+
@Suppress("NOTHING_TO_INLINE")
6566
internal inline fun <S : Segment<S>> AtomicRef<S>.findSegmentAndMoveForward(
6667
id: Long,
6768
startFrom: S,
68-
createNewSegment: (id: Long, prev: S) -> S
69+
noinline createNewSegment: (id: Long, prev: S) -> S
6970
): SegmentOrClosed<S> {
7071
while (true) {
7172
val s = startFrom.findSegmentInternal(id, createNewSegment)

kotlinx-coroutines-core/common/src/sync/Semaphore.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,9 @@ internal open class SemaphoreImpl(private val permits: Int, acquiredPermits: Int
284284
private fun addAcquireToQueue(waiter: Any): Boolean {
285285
val curTail = this.tail.value
286286
val enqIdx = enqIdx.getAndIncrement()
287+
val createNewSegment = ::createSegment
287288
val segment = this.tail.findSegmentAndMoveForward(id = enqIdx / SEGMENT_SIZE, startFrom = curTail,
288-
createNewSegment = ::createSegment).segment // cannot be closed
289+
createNewSegment = createNewSegment).segment // cannot be closed
289290
val i = (enqIdx % SEGMENT_SIZE).toInt()
290291
// the regular (fast) path -- if the cell is empty, try to install continuation
291292
if (segment.cas(i, null, waiter)) { // installed continuation successfully
@@ -325,8 +326,9 @@ internal open class SemaphoreImpl(private val permits: Int, acquiredPermits: Int
325326
val curHead = this.head.value
326327
val deqIdx = deqIdx.getAndIncrement()
327328
val id = deqIdx / SEGMENT_SIZE
329+
val createNewSegment = ::createSegment
328330
val segment = this.head.findSegmentAndMoveForward(id, startFrom = curHead,
329-
createNewSegment = ::createSegment).segment // cannot be closed
331+
createNewSegment = createNewSegment).segment // cannot be closed
330332
segment.cleanPrev()
331333
if (segment.id > id) return false
332334
val i = (deqIdx % SEGMENT_SIZE).toInt()

0 commit comments

Comments
 (0)