Thanks to visit codestin.com
Credit goes to github.com

Skip to content
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
45 changes: 32 additions & 13 deletions core/shared/src/main/scala/zio/internal/FiberRuntime.scala
Original file line number Diff line number Diff line change
Expand Up @@ -538,21 +538,29 @@ final class FiberRuntime[E, A](fiberId: FiberId.Runtime, fiberRefs0: FiberRefs,
val stack = _stack
val size = _stackSize // racy

builder += _lastTrace
var last = _lastTrace
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much more performant to keep the last variable in the stack memory instead of checking it in StackTraceBuilder which kept it in the heap

builder += last

try {
if (stack ne null) {
var i = (if (stack.length < size) stack.length else size) - 1

while (i >= 0) {
val k = stack(i)
if (k ne null) { // racy
builder += k.trace
val trace = k.trace
if (trace ne last) {
last = trace
builder += trace
}
i -= 1
}
}
}

builder += id.location // TODO: Allow parent traces?
val loc = id.location
if (loc ne last)
builder += loc // TODO: Allow parent traces?

StackTrace(self.fiberId, builder.result())
} finally {
Expand Down Expand Up @@ -844,19 +852,27 @@ final class FiberRuntime[E, A](fiberId: FiberId.Runtime, fiberRefs0: FiberRefs,
*
* '''NOTE''': This method must be invoked by the fiber itself.
*/
private def patchRuntimeFlags[R, E, A](
private def patchRuntimeFlags[E0, A0](
patch: RuntimeFlags.Patch,
cause: Cause[E0],
continueEffect: Exit[E0, A0]
): Exit[E0, A0] =
patchRuntimeFlagsCause(patch, cause) match {
case null => continueEffect
case c => Exit.Failure(c)
}

private def patchRuntimeFlagsCause[E0](
patch: RuntimeFlags.Patch,
cause: Cause[E],
continueEffect: ZIO[R, E, A]
): ZIO[R, E, A] = {
cause: Cause[E0]
): Cause[E0] = {
val changed = patchRuntimeFlagsOnly(patch)
val interruptEnabled = RuntimeFlags.Patch.isEnabled(patch, RuntimeFlag.Interruption.mask)

if (changed && interruptEnabled && shouldInterrupt()) {
if (cause ne null) Exit.Failure(cause ++ getInterruptedCause())
else Exit.Failure(getInterruptedCause())
} else if (cause ne null) Exit.Failure(cause)
else continueEffect
if (cause ne null) cause ++ getInterruptedCause()
else getInterruptedCause()
} else cause
}

/**
Expand Down Expand Up @@ -1241,12 +1257,15 @@ final class FiberRuntime[E, A](fiberId: FiberId.Runtime, fiberRefs0: FiberRefs,
}

case updateFlags: ZIO.UpdateRuntimeFlags =>
cur = patchRuntimeFlags(updateFlags.update, cause, null)
Copy link
Contributor Author

@kyri-petrou kyri-petrou Jun 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would have previously:

  1. Allocated an Exit.Failure unnecessarily
  2. Set cur = Exit.Failure(cause) which means we would have to exit the inner loop (due to the cur ne null condition), only so that we would do another loop of the outer loop to end back at the Exit.Failure case

cause = patchRuntimeFlagsCause(updateFlags.update, cause)
}
}

if (cur eq null) {
return failure
val f =
if (cause eq failure.cause) failure
else Exit.Failure(cause)
return f
}

case updateRuntimeFlags: UpdateRuntimeFlags =>
Expand Down
15 changes: 6 additions & 9 deletions core/shared/src/main/scala/zio/internal/StackTraceBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,16 @@ import scala.collection.mutable.ArrayBuilder
import scala.reflect.ClassTag

private[zio] class StackTraceBuilder private () { self =>
private var last: Trace = null.asInstanceOf[Trace]
private val builder = new ArrayBuilder.ofRef()(ClassTag.AnyRef.asInstanceOf[ClassTag[Trace]])
private[this] val builder = new ArrayBuilder.ofRef()(ClassTag.AnyRef.asInstanceOf[ClassTag[Trace]])

def +=(trace: Trace): Unit =
if ((trace ne null) && (trace ne Trace.empty) && (trace ne last)) {
def +=(trace: Trace): Unit = {
if ((trace ne null) && (trace ne Trace.empty))
builder += trace
last = trace
}
()
}

def clear(): Unit = {
def clear(): Unit =
builder.clear()
last = null.asInstanceOf[Trace]
}

def result(): Chunk[Trace] =
Chunk.fromArray(builder.result())
Expand Down