Skip to content

Workaround for debugger+compiler crash: #3625

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2431,7 +2431,7 @@ internal open class BufferedChannel<E>(
* segments, updating the counter value in [sendersAndCloseStatus] correspondingly.
*/
private fun findSegmentSend(id: Long, startFrom: ChannelSegment<E>): ChannelSegment<E>? {
return sendSegment.findSegmentAndMoveForward(id, startFrom, ::createSegment).let {
return sendSegment.findSegmentAndMoveForward(id, startFrom, createSegmentFunction()).let {
if (it.isClosed) {
// The required segment has not been found and new segments
// cannot be added, as the linked listed in already added.
Expand Down Expand Up @@ -2486,7 +2486,7 @@ internal open class BufferedChannel<E>(
* segments, updating the [receivers] counter correspondingly.
*/
private fun findSegmentReceive(id: Long, startFrom: ChannelSegment<E>): ChannelSegment<E>? =
receiveSegment.findSegmentAndMoveForward(id, startFrom, ::createSegment).let {
receiveSegment.findSegmentAndMoveForward(id, startFrom, createSegmentFunction()).let {
if (it.isClosed) {
// The required segment has not been found and new segments
// cannot be added, as the linked listed in already added.
Expand Down Expand Up @@ -2535,7 +2535,7 @@ internal open class BufferedChannel<E>(
* it always updates the number of completed `expandBuffer()` attempts.
*/
private fun findSegmentBufferEnd(id: Long, startFrom: ChannelSegment<E>, currentBufferEndCounter: Long): ChannelSegment<E>? =
bufferEndSegment.findSegmentAndMoveForward(id, startFrom, ::createSegment).let {
bufferEndSegment.findSegmentAndMoveForward(id, startFrom, createSegmentFunction()).let {
if (it.isClosed) {
// The required segment has not been found and new segments
// cannot be added, as the linked listed in already added.
Expand Down Expand Up @@ -2953,6 +2953,10 @@ internal class ChannelSegment<E>(id: Long, prev: ChannelSegment<E>?, channel: Bu
onSlotCleaned()
}
}

// WA for atomicfu + JVM_IR compiler bug that lead to SMAP-related compiler crashes: KT-55983
internal fun <E> createSegmentFunction(): KFunction2<Long, ChannelSegment<E>, ChannelSegment<E>> = ::createSegment

private fun <E> createSegment(id: Long, prev: ChannelSegment<E>) = ChannelSegment(
id = id,
prev = prev,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import kotlin.jvm.*
* Returns the first segment `s` with `s.id >= id` or `CLOSED`
* if all the segments in this linked list have lower `id`, and the list is closed for further segment additions.
*/
private inline fun <S : Segment<S>> S.findSegmentInternal(
internal fun <S : Segment<S>> S.findSegmentInternal(
id: Long,
createNewSegment: (id: Long, prev: S) -> S
): SegmentOrClosed<S> {
Expand Down Expand Up @@ -62,10 +62,11 @@ internal inline fun <S : Segment<S>> AtomicRef<S>.moveForward(to: S): Boolean =
* Returns the segment `s` with `s.id >= id` or `CLOSED` if all the segments in this linked list have lower `id`,
* and the list is closed.
*/
@Suppress("NOTHING_TO_INLINE")
internal inline fun <S : Segment<S>> AtomicRef<S>.findSegmentAndMoveForward(
id: Long,
startFrom: S,
createNewSegment: (id: Long, prev: S) -> S
noinline createNewSegment: (id: Long, prev: S) -> S
): SegmentOrClosed<S> {
while (true) {
val s = startFrom.findSegmentInternal(id, createNewSegment)
Expand Down
6 changes: 4 additions & 2 deletions kotlinx-coroutines-core/common/src/sync/Semaphore.kt
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,9 @@ internal open class SemaphoreImpl(private val permits: Int, acquiredPermits: Int
private fun addAcquireToQueue(waiter: Any): Boolean {
val curTail = this.tail.value
val enqIdx = enqIdx.getAndIncrement()
val createNewSegment = ::createSegment
val segment = this.tail.findSegmentAndMoveForward(id = enqIdx / SEGMENT_SIZE, startFrom = curTail,
createNewSegment = ::createSegment).segment // cannot be closed
createNewSegment = createNewSegment).segment // cannot be closed
val i = (enqIdx % SEGMENT_SIZE).toInt()
// the regular (fast) path -- if the cell is empty, try to install continuation
if (segment.cas(i, null, waiter)) { // installed continuation successfully
Expand Down Expand Up @@ -325,8 +326,9 @@ internal open class SemaphoreImpl(private val permits: Int, acquiredPermits: Int
val curHead = this.head.value
val deqIdx = deqIdx.getAndIncrement()
val id = deqIdx / SEGMENT_SIZE
val createNewSegment = ::createSegment
val segment = this.head.findSegmentAndMoveForward(id, startFrom = curHead,
createNewSegment = ::createSegment).segment // cannot be closed
createNewSegment = createNewSegment).segment // cannot be closed
segment.cleanPrev()
if (segment.id > id) return false
val i = (deqIdx % SEGMENT_SIZE).toInt()
Expand Down