As I understand it, Kotlin coroutines generate what is known as irreducible control flow. This means that loops have more than one entry point, or equivalently, there are loops that have a goto jumping into the body from the outside. (Java the language and I believe also Kotlin the language don't have goto, but the Java bytecode does.)
Irreducible loops make many optimizations much more complex. Bytecode generated by javac never contains irreducible loops, and since bytecode generated by javac is the number 1 use case targeted by JVM JIT compilers, they probably just don't bother trying to be that smart about irreducibility.
Irreducible loops make many optimizations much more complex. Bytecode generated by javac never contains irreducible loops, and since bytecode generated by javac is the number 1 use case targeted by JVM JIT compilers, they probably just don't bother trying to be that smart about irreducibility.