Add documentation on planned inline changes.
^KT-64570
This commit is contained in:
committed by
Space Team
parent
09713bb89e
commit
01c16ed736
@@ -0,0 +1,95 @@
|
||||
# Basic step-by-step inlining example for proposed model
|
||||
|
||||
Let's check the following code:
|
||||
```kotlin
|
||||
// lib
|
||||
fun process(x: Int) { /* some code here */ }
|
||||
inline fun run(block: () -> Int) = process(block())
|
||||
// main
|
||||
fun foo() {
|
||||
run { 42 }
|
||||
}
|
||||
```
|
||||
|
||||
We would dig deeper into the compilation of the main module, assuming lib is already compiled.
|
||||
|
||||
|
||||
After frontend execution, we get something like that. Here we have all calls resolved.
|
||||
Functions from dependencies (lib) are loaded as LazyIr.
|
||||
|
||||
```kotlin
|
||||
fun foo() : Unit {
|
||||
run(
|
||||
lambda@{ return@lambda 42 }
|
||||
)
|
||||
}
|
||||
|
||||
// dependencies:
|
||||
// lazyIR without bodies
|
||||
fun process(x: Int): Unit
|
||||
inline fun run(block: Function0<Int>)
|
||||
// ... lazyIR for Int, Unit, Function and so on
|
||||
```
|
||||
|
||||
Then, pre-inline lowering happens. But as we have a very simple example, there is nothing to do.
|
||||
|
||||
Next, we need to load Ir of run function. For that we need to run Deserializer. But we can't run linker,
|
||||
so references inside function body wouldn't be resolved.
|
||||
|
||||
```kotlin
|
||||
// IrFunction
|
||||
// name = run
|
||||
// isInline = true
|
||||
// valueParameter0
|
||||
// irType
|
||||
// classifier = Lazy class kotlin.Function0 (from Lazy run function)
|
||||
// typeArgument0 = Lazy class kotlin.Int (from Lazy run function)
|
||||
// returnType = Lazy class kotlin.Unit (from Lazy run function)
|
||||
// body
|
||||
// IrCall symbol = Unbound function symbol with signature "process(Int) : Unit"
|
||||
// returnType = IrType classifier = Unbound class symbol with singnature kotlin.Unit
|
||||
// valueArgument0 =
|
||||
// IrCall symbol = Unbound function symbol with signature Function0.invoke()
|
||||
// typeArgument0 = IrType classifier = Unbound class symbol with singnature kotlin.Int
|
||||
// valueArguemnt0 = IrGet valueParamenter block
|
||||
// type = Unbound class symbol with singnature kotlin.Int
|
||||
//
|
||||
inline fun run(block: Function0<Int>) : Unit { // note, that here we merged LazyIr of run function with deserialized body
|
||||
process(block.invoke())
|
||||
}
|
||||
```
|
||||
|
||||
Now this function can be inlined to original.
|
||||
|
||||
```kotlin
|
||||
// IrFunction
|
||||
// name = foo
|
||||
// returnType = Lazy class kotlin.Unit
|
||||
// body
|
||||
// IrReturnableBlock symbol=symbol1
|
||||
// type = Lazy class kotlin.Unit
|
||||
// IrInlinedFunctionBlock required for debug information
|
||||
// IrReturn
|
||||
// target=symbol1
|
||||
// value = IrCall
|
||||
// symbol = Unbound function symbol with signature "process(Int) : Unit"
|
||||
// returnType = IrType classifier = Unbound class symbol with singnature kotlin.Unit
|
||||
// valueArgument0
|
||||
// IrReturnableBlock symbol=symbol2
|
||||
// type = Lazy class for kotlin.Int
|
||||
// IrInlinedFunctionBlock required for debug information
|
||||
// IrReturn target=symbol2 value = IrConst<Int>(42)
|
||||
fun foo() : Unit {
|
||||
inlinedBlock@{
|
||||
return@inlinedBlock process(lambda@ { return@lambda 42 })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Several side notes on the result:
|
||||
1. We have both lazy references to kotlin.Unit/kotlin.Int and unbound ones in the tree now.
|
||||
It is fine, as we only need to deserialize it now.
|
||||
2. While inlining we need to understand that we need special handling of
|
||||
`Unbound function symbol with signature Function0.invoke()`, this must be done by signature only.
|
||||
3. IrReturnableBlock is represented like it works now, while IrInlinedFunctionBlock is significantly simplified.
|
||||
Probably we need to redesign both to make them serializable.
|
||||
Reference in New Issue
Block a user