Commit Graph

187 Commits

Author SHA1 Message Date
Ilmir Usmanov 822c14814b Revert "Completely rewrite reifiedIntTypeAnalysis, making it more streamline"
This reverts commit 1ed4324613.

Otherwise, bootstrap is broken.
2020-06-03 19:43:59 +02:00
Ilmir Usmanov 1ed4324613 Completely rewrite reifiedIntTypeAnalysis, making it more streamline
and easy to understand and optimize if it would be a bottleneck.
Use LVT to get information of refined int type in one specific case

 #KT-38925 Fixed
2020-06-03 16:03:50 +02:00
pyos 35460fed19 JVM_IR: fix a bug when isInlineParameter is applied to default stubs
If an inline parameter has a default value, its type is nullable.
There's already code to handle this in `IrInlineCodegen`, but it
really should be in `isInlineParameter` instead, otherwise e.g.
SyntheticAccessorLowering fails.
2020-05-29 10:04:36 +02:00
Dmitry Petrov a270ee094c Language feature for new inline class mangling rules (since 1.4) 2020-05-29 00:53:01 +03:00
pyos d17a18f96d JVM: do not write trivial SMAPs to classes outside inline funs
where trivial == those that map the file to itself.
2020-05-25 20:03:56 +02:00
Mikhail Bogdanov 16b4342d92 Add minor test for SMAP
Relates to PR 3248
2020-05-19 18:34:56 +02:00
Ilmir Usmanov d6d331de2a Minor. Fix test 2020-05-08 19:36:02 +02:00
Ilmir Usmanov 05797afaf8 Replace last SourceInterpreter with specific one in inliner
#KT-38489: Fixed
2020-05-07 23:04:03 +02:00
Ilmir Usmanov 2c88844409 Replace SourceInterpreter with interpreter, which track only
functional arguments.
2020-05-07 23:04:01 +02:00
Alexander Udalov 098a935aa7 Fix exponential string table size of anonymous classes during inlining
When we inline an anonymous object which captures something such as
crossinline values or reified parameters, we copy and transform its
metadata in `AnonymousObjectTransformer.transformMetadata`. Basically we
read the metadata of the original class, add a minor protobuf extension
and write it to the new class.

This also includes copying the string table. We read the string table
into `JvmNameResolver` (a representation of string table used in
deserialization), then construct a `JvmStringTable` (a representation
used in _serialization_) and then write it back.

There's a few optimizations in the string table representation in JVM
metadata which allow to store less strings and thus take less space. See
`StringTableTypes.Record` in `jvm_metadata.proto` for more information.
One of the optimizations `Record.range` allows to avoid storing the same
record many times in a sequence. For example, if we have N different
strings in the string table but none of them require any operation (such
as substring, char replacement, etc.), then we only store the record
with all default values (no operation, no predefined string, etc.) and
set its `range` to N. Upon reading such optimized record list in
`JvmNameResolver`, we "expand" it back to normal, so that we could index
it quickly and figure out what operation needs to be performed on each
string from the string table.

The problem was that when we expanded this list, we didn't set the range
of the expanded record entry to 1. So each record in
`JvmNameResolver.records` still has its original range. It doesn't cause
any problems most of the time because the range in this expanded list is
almost unused. However, when copying/transforming metadata for anonymous
objects, we mistakenly passed this expanded list with incorrect ranges
to `JvmStringTable`. So the metadata in the copied anonymous object
ended up being incorrect: each record now was present the number of
times equal to its range. Copying such metadata once again led to
another multiplication of the record list size. Multiple copies resulted
in exponential increase in memory consumption and quickly led to OOM.

For the fix, we now take the original, unexpanded list of records when
creating `JvmStringTable` out of `JvmNameResolver` for transformation of
anonymous object metadata.

Note that another possible fix would be to make range for each record in
`JvmNameResolver.records` equal to 1. This is undesirable though, since
then we'd need to copy each `JvmProtoBuf.StringTableTypes.Record`
instance, of which there could be many, and use some memory for no
apparent gain (since ranges in that expanded list are now not used at
all).

 #KT-38197 Fixed
2020-04-28 12:59:52 +02:00
pyos 456469eb3b JVM: fix remapping of new T inside regenerated copies of T
In general, `InliningContext.findAnonymousTransformationInfo` was not
reliable because it mapped each type to *some* info for that type,
preferring ones with `shouldRegenerate == true` if those exist. Thus, it
returned incorrect results if one type was regenerated multiple times,
e.g. in a nested inlining context or because of a `finally` (which
duplicates anonymous objects). The solution is to avoid a global map and
attach the current transformation info directly to the current inlining
context.
2020-04-23 14:20:54 +02:00
Mikhail Bogdanov 1772f20d48 Minor. Add smap test for multifile facade 2020-04-08 07:26:55 +02:00
pyos b3e124ad66 Add a test where classes call inline functions from each other 2020-04-08 07:04:16 +02:00
pyos 516692008f JVM: add tests fixed by the last two commits
One was broken on JVM, the other on JVM_IR.
2020-04-07 15:42:41 +02:00
pyos 5ed845d0b4 JVM_IR: reuse same bodies for suspend funs and $$forInline versions 2020-04-03 19:51:45 +02:00
pyos e98bdc6f8e JVM: preserve call site markers when inlining lambdas
and default functions into their own stubs.

Fixes #KT-35006
2020-03-31 16:06:57 +02:00
pyos 9d21800d8f JVM: fix SMAP range extension logic
If `mapLineNumber` was called in non-monotonic order, e.g. N then N+2
then N+1, the first two calls created a range that spans [N; N+2] but
the third call did not reuse it.
2020-03-31 16:06:57 +02:00
Igor Chevdar d808ef10b2 Added some tests on local classes in inline bodies 2020-03-28 15:26:19 +03:00
pyos be37e7135a Add a test for SMAPs with interleaved files 2020-03-25 14:03:32 +01:00
pyos 4558d48481 JVM: add a language feature to omit *E between SMAP strata
Fixes #KT-37704
2020-03-25 10:33:59 +01:00
pyos 2c06503311 JVM_IR: partially fix inline methods using captured crossinline lambdas
The fields containing crossinline lambdas should be package-private to
avoid generating synthetic accessors, which break object regeneration.

Note that the inline methods cannot actually be called, as call sites
will attempt to read the captured lambda from a field through a *copy*
of the local containing the object, so these reads will not be inlined,
causing an exception at runtime:

    inline fun f(crossinline g: () -> Unit) = object : I {
        inline fun h() = g()
        // effectively `val tmp = this; return tmp.$g()`:
        override fun run() = h()
    }

    f {}.run() // NoSuchFieldError: $g

This particular example can be fixed by reusing locals for receiver
parameters in IrInlineCodegen, but explicitly assigning `this` to
another variable and calling an inline method on it will break it again.
(This is only applicable to the JVM_IR backend, as the non-IR one fails
to generate `f` at all for some other reason.)
2020-03-18 13:13:54 +01:00
pyos 2e542da91d JVM_IR: fix accesses from crossinline lambdas in other packages again 2020-03-17 16:38:32 +01:00
pyos bdd88e1655 JVM_IR: place suspend markers in faux lambdas around inline references
Otherwise, the assumption that coroutine codegen makes about every
inlined function already having the markers breaks and it is no longer
true that calls to inline lambdas do not require them.
2020-03-13 18:33:41 +01:00
pyos dc388f3f3a JVM_IR: add a test for suspend inline fun with defaults in a class
This is one example of a function replaced by a lowering after
AddContinuationLowering mentioned in the last commit: the lowering that
makes default stubs static is further down. Although this is not a
lambda, calling getOrCreateSuspendFunctionViewIfNeeded on it in the
inliner is fatal all the same.
2020-03-09 17:05:42 +01:00
Mark Punzalan a732e8f5fe [JVM IR] Ensure there is one accessor for each super access from a
subclass when there are multiple subclasses in a file.
2020-03-06 22:59:52 +01:00
pyos 8487211ae1 JVM_IR: refine the condition for mangling names of multifile members
Private $$forInline versions of public suspend functions should not
be mangled. (Note that there are no $$forInline versions of private
suspend functions, as those are effectively inline-only.)
2020-03-06 14:33:50 +01:00
Alexander Udalov 0f7122a88a Support MutablePropertyReferenceN supertypes in LambdaInfo
#KT-37087 Fixed
2020-03-05 14:01:30 +01:00
pyos 159d292ea7 JVM_IR: make continuation detection more consistent
* unify various checks for whether a suspend function needs a
    continuation;

  * mark the continuation parameter with an origin (this also allows
    correctly computing the offset of the local in codegen -- see the
    new test);

  * when wrapping `suspend fun main`, use a suspend reference instead of
    a synthetic non-suspend lambda (required to correctly implement the
    previous point, as previously the continuation parameter was passed
    to main() itself correctly only because of very lenient checks in
    AddContinuationLowering).
2020-03-03 15:12:13 +01:00
pyos 39ebc8cfa5 Add a suspend test that fails on JVM_IR 2020-02-21 12:11:19 +01:00
pyos 2bf50cc91a JVM_IR: correctly name $$forInline versions of @JvmName suspend funs
Using a hack similar to $default stubs.
2020-02-07 12:16:26 +01:00
Ilmir Usmanov 7dfd7b6081 Spill stack before analyzing it when looking for non-inline suspend lambda
parameters of inline function. Otherwise, it leads to AnalyzerException,
when inlined lambda contains try-catch block. The reason is simple:
in try block, we leave some variables on stack, while on catch block the
stack is empty. Spilling the variables before try block does the trick.
 #KT-34708 Fixed
2020-02-06 13:10:21 +01:00
pyos bda5b0d5a9 JVM_IR: further refine synthetic accessor generation
References to protected members from crossinline lambdas in the same
package do not need accessors.
2020-01-31 13:20:30 +01:00
Alexander Udalov 2fca7f1a54 Add codegen tests for old behavior of null checks
#KT-22275
2020-01-24 11:56:28 +01:00
pyos 2f0f4e570f JVM_IR: do not remap locals in contexts nested inside lambdas
The only case where this code is reachable at all is objects in lambdas
that use reified type parameters of the outer inline function. Since the
type parameters are declared outside the inlining root, regenerating the
object is actually pointless, and remapping its captures even more so
(not to mention that the code under the condition uses the captures of
the lambda, not of the method it's currently transforming).
2020-01-22 15:36:09 +01:00
Alexander Udalov f48bdc1fcb Fix codegen box tests for language version 1.4
Since API version 1.4, NullPointerException is thrown for casts of null
to any type instead of TypeCastException.
2020-01-20 19:12:59 +01:00
Ilmir Usmanov 6ede10c1ca JVM_IR: Minor. Add test for SMAP of inner object/lambda of inline suspend function 2020-01-20 16:00:36 +01:00
pyos 99eab5a058 IR: unify 3 copies of function body remapping
Also,

  1. remove some redundant copies;

  2. fix remapping of non-local returns in lambdas if the body is moved
     after LocalDeclarationsLowering (the lambda is no longer inside the
     body, but must still be visited)
2020-01-14 18:48:27 +03:00
Alexander Udalov 8a4510c21b Regenerate tests 2020-01-02 10:31:00 +01:00
Mikhael Bogdanov 4b6202c902 JVM_IR. Support inlining of bound CR 2019-12-30 08:35:46 +01:00
Igor Chevdar cca3f13e48 Added multi-module test on inline functions 2019-12-18 12:45:41 +03:00
Mikhael Bogdanov 03c2350e79 Keep original casts during reification to avoid VerifyError
#KT-26435 Fixed
2019-12-17 12:41:22 +01:00
Dmitriy Novozhilov e7f8c8e155 [TEST] Regenerate tests after previous commit 2019-12-12 16:11:45 +03:00
Mikhael Bogdanov 26032e4297 Split exception table on finally insertion before non-local return
in nested try blocks without finally

 #KT-31653 Fixed
2019-12-12 13:33:40 +01:00
Ilmir Usmanov df0a86ea57 Add NOP as first instruction in coroutine's try blocks
#KT-35035 Fixed
2019-12-11 15:01:41 +01:00
Mikhael Bogdanov b9dee4e93a Remove assertion on sorted ranges: it could be empty if lambda doesn't contain any linenumber
#KT-35101 Fixed
2019-12-02 12:08:36 +01:00
Mikhael Bogdanov cf6f823d29 Use descriptor from resolved call to inline accessors
In case of inline it should be same descriptor (except of fake override), In general case getter could be synthetic accessor and in such case it's not inline
2019-11-29 13:15:42 +01:00
Mikhael Bogdanov d28ec1d449 Add test for default lambda inlining in suspend inline 2019-11-20 12:57:41 +01:00
pyos 82fb5c4d19 JVM_IR: move lambda captures to end of signature when inlining
For example, a lambda `{ param -> captured }` of type `E.(T) -> U` will
be transformed by LocalDeclarationsLowering into a private static method

    fun f$lambda-0($this: E, $captured: U, param: T) = $captured

The reason for such an ordering is that a lambda looks the same as a
local function, and local function can have default arguments, and those
arguments can reference captured variables; thus, captured variables
must come before actual declared arguments.

However, this is not the order that the inliner wants. Moreover, since
it was written to handle lambdas represented as `invoke` methods of
anonymous objects, it does not expect the actual callable method to have
any parameters corresponding to captured variables at all. This results
in it attempting to generate a temporary node with descriptor

    (LE;LU;LT;LU;)LU;

while still using locals 1 and 2 as `param` and `$captured` respectively.
In the example above, this is not critical, as they both have reference
type and the lambda will eventually be pasted into a different node
anyway; however, if it happens that one of them is a primitive, or both
are primitives of different types, the bytecode will use incorrect
instructions, causing verification errors. The correct descriptor is

    (LE;LT;LU;)LU;
2019-11-11 13:46:42 +01:00
pyos 5d8aac456f JVM_IR: create temporaries for complex super constructor arguments
As for SAM wrappers, the bytecode sequence

    new A
    dup
    new B
    dup
    invokespecial B.<init>
    invokespecial A.<init>

breaks the inliner, so instead we do

    new B
    dup
    invokespecial B.<init>
    store x
    new A
    dup
    load x
    invokespecial A.<init>
2019-11-06 15:54:40 +01:00
pyos 862197d713 JVM_IR: create temporaries for complex SAM conversion arguments
To avoid bytecode sequences like

    new _1Kt$sam$i$java_lang_Runnable$0
    dup
    new _1Kt$f$1
    dup
    invokespecial _1Kt$f$1.<init>()V
    invokespecial _1Kt$sam$i$java_lang_Runnable$0.<init>(...)V

as the different order of `new` and `<init>` confuses the inliner.
2019-11-06 15:54:40 +01:00