I agree with @JanKanis, and disagree with my teammates from JetBrains that we need to compile Kotlin directly to LLVM. Unfortunately, I could not push my opinion to my teammates, so it remains my personal opinion.
Kotlin is an awesome languages for JVM, created WRT good interop with Java and with tons of Java libraries. Indeed, there are some disadvantages in JVM, at least, in OpenJDK, like large runtime size, JIT (as opposed to AOT) which can be inacceptable in some cases, unpredictable GC pauses, etc. That does not mean, however, that we should compile Kotlin ourselves directly to LLVM. This means that we need more appropriate JVM implementation. There are some, like RoboVM, MOE, etc. We can pick one and contribute our code there. We can even invent our own JVM AOT, it’s not that hard, at least comparing to Kotlin Native which has to implement semantics which is close to JVM. I see some advantages there:
- We don’t have to do large amout of work, we can easily start with what we have and then make things better.
- We could get a good adoption from people who have experience with Java and a little unsure to start using Kotlin. With JVM AOT approach they could write most of their code in Java and start to write some of the code in Kotlin (and fall in love with it). With current approach these people either refuse to port their app to iOS at all or discover and use MOE.
Let me tell about some myths about “ugly monstrous JVM”
- JDK is not necessary large. It is, but we can cut only parts necessary for embedded/AOT/iOS/games/whatever else, and it can be small enough. We can even use minifier like proguard or write our own one, which is capable of eliminating unused classes and methods.
- JVM is not necessarily JIT. We can sacrifice some ClassLoader features to have chance of creating pure AOT. AFAIK, RoboVM does not support class loaders, and it’s not a big limitation for iOS and embedded development.
- JVM implementation is not tied to GC, any automatic memory management mechanism is acceptable, including ARC, region-based memory management, etc.
- JVM is heavyweight. JVM bytecode consists of very simple instructions that remind of assembler. Full spec describes about 200 instruction versus x86 architecture which has thousands of instructions. Most of instructions are like iadd, fadd, isub, fsub, etc, which are trivially mapped to LLVM IR.
- GC does not necessarily produces unpredictable pauses, there are GC scheduling algorithms that give strong guarantees of upper limit of time spent in GC.