Replace coercion from VOID with call 'pushDefaultValueOnStack'
It's necessary because coercion of VOID to java/lang/Object ends with Unit instance on stack
that makes variables spilling algorithm thinking that variable is Unit
#KT-13409 Fixed
Before this change everything works just fine for 'handleResult' methods
accepting non-Unit parameters
For other cases the same coercion-to-unit strategy is in plain lambdas:
- if last statement is not Unit type, execute it, pop from the stack, then put Unit instance
- for 'return@label' (no expression) just put Unit on the stack
#KT-13531 Fixed
It fixes VerifyError with coroutines on Dalvik happening because of
variables spilling before/after suspension point
BasicInterpreter from ASM does not distinct 'int' types from other
int-like types like 'byte' or 'boolean', neither do HotSpot and JVM spec.
But it seems like Dalvik does not follow it, and spilling
boolean value into an 'int' field fails with VerifyError on Android 4,
so it's necessary to distinct int types for variables spilling
#KT-13289 Fixed
As well as for other kinds of expressions
Within attached test they were generated twice in case of last expression of coroutine block,
because coroutine related codegen part is built upon assumption that all expressions should be generated lazily
Also add a test about unary postfix increment/decrement
#KT-13156 Fixed
Do not treat var as alive just because current instruction belongs to an item range
in local variables table, but the item has different sort of type
As liveness analysis is mostly used in coroutines spilling,
not applying this change may lead that to problems on Android (see tests)
At first we try to resolve 'handleResult' just as last expression
in a lambda is first argument, then if results are unsuccessful
try resolve 'handleResult' with fake Unit expression
#KT-12969 Fixed
As well as all other kinds of expressions
While it's not necessary in a sense that 'for' loop can not be plain expression,
i.e. it can't be an argument for safe-call etc., but laziness is still very convenient property.
E.g. within attached test they were generated twice in case of last expression
of coroutine block, because coroutine related codegen part is built upon
assumption that all expressions should be generated lazy.
A lot of additional work was required to support them:
- Suspension points are being identified by two markers
instead of one pointing to suspend function call
- Approach with replacing return type of suspend function does not work anymore.
So we decode suspension return type as an argument for begin marker
- It became necessary to perform variables liveness analysis
(see comment in org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor.spillVariables)
Without this change internal error happens while inlining coroutine code with try/catch inside
Also get rid of hack with SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC
See comment within MethodAnalyzer for clarification
Instead of performing signature change during transformation
it's convinient to make just when generating corresponding call,
for example there is no need to think about default parameters as they just work as is
See comment above replaceSuspensionFunctionViewWithRealDescriptor for clarification
- Use proper class descriptor when retreiving continuation object (see previous commit)
- Use return type as VOID for such cases
- Load correct labels related to coroutine lambda from outer context
Before this commit context.getThisDescriptor() has been used, that was quite correct
until suspension happens inside inlined lambda (it has different this-descriptor)