Previous version of the boxing/unboxing analysis treated merging boxed and non-boxed values as a hazard.
If such merged values are not used (e.g., early return + local variables reused in inlined calls),
corresponding boxing/unboxing operations still can be optimized out.
All information related to boxed value usage by instructions is moved to 'BoxedValueDescriptor'.
Introduce "tainted" (and "clean") boxed values, with the following rules:
merge(B, B) = B, if unboxed types are compatible,
T, otherwise
merge(B, X) = T
merge(T, X) = T
where
X is a non-boxed value,
B is a "clean" boxed value,
T is a "tainted" boxed value.
Postpone decision about value merge hazards until a "tainted" value is used.
While within a method by the JVM spec null-value has a special
Nothing-like type, when we spill it for a coroutine, we must choose
some real type to CHECKCAST to after restoring the variable's value.
But the problem is that such a real type depends on usage of that null value,
and there may be more than one usage.
The solution is not to spill such variables into fields, but instead
init them with ACONST_NULL after each suspension point
#KT-16122 Fixed
The main problem is that inside a state machine for a named suspend
function parameters of it's owner are available as a usual captured
closure parameters (i.e. through synthetic fields), while
TailRecursion codegen expects that parameters are straight local
variables.
So, the solution is just to define local var for each of real parameters
(all but the last continuation parameters) for tailrec functions.
#KT-15759 Fixed
Array instatiation code should handle type alias constructors properly.
So far, we don't have constructors with type parameters
different from the type parameters of the resulting type,
so we can safely take type arguments of the underlying type.
The problem was that we spilled the `origin` variable (see test) as Object, because
we determined the type of merge(null, String) incorrectly.
#KT-15973 Fixed
Suspend function call with a reachable (alive) begin marker and unreachable (dead) end marker
is an exit point for the corresponding coroutine.
It isn't a suspension point, and doesn't introduce a new state in the coroutine FSM.
- Determine if there are non-tail calls to getValue/setValue simply
by existance of such a property
(it might be too strict, but implementing more granular check may be rather hard)
- Change in ExpressionCodegen is relevant for provideDelegate,
that in case of local variables uses OnStack as StackValue
(see the comment near these changes)
#KT-15933 Fixed
1. JVM view of suspend accessors must be also an instance of AccessorForFunctionDescriptor,
thus `createSubstitutedCopy` should be correctly overidden.
2. accessibleFunctionDescriptor should unwap the initial suspend descriptor,
for the same reasons as for type aliases constructors and etc:
these descriptors are used as keys of the map of accessors, so
to avoid duplication for suspend view and initial suspend descriptor,
we always use the latter one as a key.
#KT-15907 Fixed
#KT-15935 Fixed
When the extension receiver of a named suspend function was marked as used
from the inner lambda, codegen used to throw a "Don't know how to generate outer expression for class" exception.
It may seem quite tricky, but currently for suspend lambda body
its extension receiver is treated as it's defined inside the relevant "doResume"
(there is an actual bytecode part that fills the relevant local variable)
The problem was that inside ExpressionCodegen for "doResume" of named
suspend function we couldn't determine that original function has
an extension receiver.
#KT-15821 Fixed
#KT-15820 Fixed
If all the suspension calls in a suspend function were "hidden"
under the for-convention (iterator/next/hasNext) calls,
control-flow didn't find them, thus supposing that there is no
suspension points and there is no need to generate a coroutine state machine
The solution is to add relevant calls to CFG
#KT-15824 Fixed
Do not report an error on enum entry without initializer if all parameters have default values
(error is still reported if there is no such constructor, or if the constructor call is ambiguous).
Record resolved call on KtEnumEntry.
NB is the enum entry has a corresponding subclass, we still have to generate the "default" constructor call,
because FE doesn't know about the platform-specific representation of that class and its constructors.
See also KT-14097, KT-15900
#KT-10711 Fixed
#KT-12802 Fixed
#KT-12964 Fixed
#KT-15439 Fixed
Analyze callable references in `dependent` mode, then complete them with
respect to expected types
These two functions are supposed to fix an inconvenience in the design of
KProperty{1,2}.getDelegate for extension properties, where you have to pass an
instance of the extension receiver which is going to be completely ignored
#KT-8384 Fixed
See doNotCaptureSupertype test for clarification:
When resolving b.collect(toList()) we're building a common system with
two variables T and R.
The problem was that when introducing the constraint
C<T, Inv<T>> <: C<in String, R> we then were seeing the constraint
T <= in String, and add the constaint T=Captured(in String)
That lead to R=Inv<T>=Inv<Captured(in String)>, and after approximation
R=Inv<in String>, that is not the desirable result (Inv<String> suits here)
But the root problem was that we add captured constaint when projection was from supertype,
that seems to be wrong, and for example Java doesn't do that in the similar situation.
#KT-11259 Fixed
The problem is that code in the attached test led to VerifyError at runtime
because the Bar's uninitialized instance created in 'map' was being stored
to the field (leaked from the JVM point of view).
The actual problem was that after repeating visiting of NEW operation
we used to drop the set of already visited copy usages.
For clarification see the comment before 'processUninitializedStores'
#KT-15016 Fixed