Commit Graph

442 Commits

Author SHA1 Message Date
pyos
ef5fe0675a JVM_IR: refactor suspendFunctionView
fixing the check for DescriptorWithContainerSource in the process
(containerSource *may* be null).
2020-01-08 19:52:20 +01:00
Mikhael Bogdanov
4b6202c902 JVM_IR. Support inlining of bound CR 2019-12-30 08:35:46 +01:00
Georgy Bronnikov
d4b0151f51 JVM_IR: fix name of received field for suspend lambdas
$ at the start caused AnonymousObjectTransformer to skip the field.
2019-12-23 18:03:46 +01:00
Ilmir Usmanov
9292022f88 JVM_IR: Support inner lambdas which capture crossinline 2019-12-23 18:03:42 +01:00
Ilmir Usmanov
daa76cbf1e JVM_IR: Support inner objects with multiple suspend functions
Do not clean `functionsToAdd`
2019-12-23 18:03:41 +01:00
Ilmir Usmanov
a1448ebb37 JVM_IR: Support crossinline suspend lambdas
The main idea is the following: since we need to generate
(fake)continuations before inlining, we move IrClasses of suspend
lambdas and continuation classes of named functions into the functions.
Thus, it allows the codegen to generate them prior to inlining and
the inliner will happily transform them for us.
Because of that, lowerings which transform call-site function are likely
to change reference to lowered suspend lambdas or functions.
Hence, do not rely on references to lowered suspend lambdas or
functions, instead, rely on attributes.

Do not generate continuation for inline suspend lambdas.
Previously, inline suspend lambdas were treated like suspend functions,
thus we generated continuations for them. Now we just do not treat them
as suspend functions or lambdas during AddContinuationLowering.
We should add continuation parameter to them, however.

Do not generate secondary constructor for suspend lambdas, otherwise,
the inliner is unable to transform them (it requires only one
constructor to be present).

Generate continuation classes for suspend functions as first statement
inside the function.
This enables suspend functions in local object inside inline functions.
Since we already have attributes inside suspend named functions, we
just reuse them to generate continuation class names. This allows us
to close the gap between code generated by old back-end and the new
one.

If a suspend named function captures crossinline lambda, we should
generate a template for inliner: a copy of the function without
state-machine and a continuation constructor call. The call is needed
so the inliner transforms the continuation as well.

Refactor CoroutineTransformerMethodVisitor, so it no longer depends on
PSI.
2019-12-23 18:03:40 +01:00
pyos
a4b005fd5d PSI2IR: generate field writes for all val property assignments
Assuming the frontend is correct, and it hopefully is, all of them are
initializations even if not done in the owner class directly.
2019-12-20 13:03:39 +03:00
Mikhael Bogdanov
650cfeaaed Update inline tests to void PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR 2019-12-19 12:46:36 +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
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
Alexander Udalov
a485a5ffd6 JVM IR: load fields for JvmField properties from dependencies
This is needed to properly lower JvmField property calls to field
accesses.
2019-11-20 15:35:12 +01:00
Mikhael Bogdanov
d28ec1d449 Add test for default lambda inlining in suspend inline 2019-11-20 12:57:41 +01:00
Mikhael Bogdanov
19ce055322 JVM_IR. Pass stub function reference in 'getSignature' 2019-11-20 12:57:38 +01:00
Mikhael Bogdanov
ac31e0e8c7 Support default lambda inlining in IR 2019-11-20 12:57:36 +01:00
pyos
ce0fb662c0 JVM_IR: fold inline lambdas when computing OUTERCLASS
so that the enclosing method of objects defined inside lambdas is the
one they are declared in.

Note that this does not fix *all* enclosingInfo tests because JVM_IR
currently follows the KT-28064 proposal, i.e. does not regenerate
objects defined inside lambdas under any circumstances. For example,
this causes test boxInline/enclosingInfo/inlineChain2.kt to fail because
the enclosing method of objects is _2Kt.box instead of (non-existent in
source code) `_2Kt$box$inlined$call$1.invoke` or whatever. What's more
important is that OUTERCLASS no longer points to a non-existent
`box$lambda-N` and therefore `.enclosingMethod` no longer throws.
2019-11-12 12:44:46 +01:00
pyos
f906524d76 Mark a SAM conversion test as JVM-only 2019-11-12 12:24:55 +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
433e0e4740 JVM_IR: remember facade fqnames of imported classes
Necessary to support importing file classes annotated @JvmPackageName,
since the actual package fragment they are a part of has the name from
the `package` declaration.
2019-11-11 13:31:57 +01:00
pyos
fb9f43c119 JVM_IR: fix load check in inliner (should accept primitives too) 2019-11-07 15:58:44 +01:00
Alexander Udalov
4164b620e8 Minor, remove obsolete directives and suppressions from contracts test data 2019-11-07 15:20:34 +01:00
Alexander Udalov
66e19b13ce IR: create shared variables for val-variables when needed
This is possible when a lambda's contract guarantees initialization of a
variable.
2019-11-07 15:20:34 +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
42f75b3247 JVM_IR: have SAM wrapper constructors accept FunctionN
Otherwise, the cached instances cannot be reused for different wrapped
types. Also, if the wrapped type is regenerated during inlining, the
inliner would produce a call to a nonexistent constructor that takes the
regenerated type as an argument.
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
pyos
4fc1bd9ec5 Support inlining functions with KT-28064 style objects
Namely, anonymous objects defined in lambdas that have all captured
variables as loose fields instead of a single reference to the parent.

The question is, when a lambda inside an inline function defines an
anonymous object, and that object is not regenerated during codegen for
the inline function itself, but then has to be regenerated at call site
anyway, do we use an outer `this` or loose capture fields? For example,
before KT-28064:

    inline fun f1(g: () -> Unit) = object { g() }
    // -> f1$1 { $g: () -> Unit }
    inline fun f2(g: () -> Unit) = f1 { object { g() } }
    // -> f2$$inlined$f1$1 { $g: () -> Unit }
    //    f2$$inlined$f1$1$lambda$1 { this$0: f2$$inlined$f1$1 }
    inline fun f3(g: () -> Unit) = f2 { object { g() } }
    // -> f3$$inlined$f2$1 { $g: () -> Unit }
    //    f3$$inlined$f2$1$1 { this$0: f3$$inlined$f2$1 }
    //    f3$$inlined$f2$1$1$lambda$1 { this$0: f3$$inlined$f2$1$1 }

After KT-28064:

    inline fun f2(g: () -> Unit) = f1 { object { g() } }
    // -> f2$$inlined$f1$1 { $g: () -> Unit }
    //    f2$1$1 { $g: () -> Unit }
    inline fun f3(g: () -> Unit) = f2 { object { g() } }
    // -> f3$$inlined$f2$1 { $g: () -> Unit }
    //    f3$$inlined$f2$2 { ??? }
    //    f3$1$1 { $g: () -> Unit }

Should `???` be `this$0: f3$$inlined$f2$1` or `$g: () -> Unit`? This
commit chooses the latter for KT-28064 bytecode and keeps `this$0` when
inlining the old bytecode.
2019-11-06 13:11:44 +01:00
Steven Schäfer
0da4b06074 psi2ir: Fix return insertion
We should only insert a return statement at the end of a lambda or
function if the final statement is used as an expression (slice
USED_AS_RESULT_OF_LAMBDA and USED_AS_EXPRESSION).
2019-10-31 11:13:44 +03:00
pyos
a835f07d51 JVM_IR: don't regenerate objects in lambdas inlined into objects 2019-10-31 09:09:54 +01:00
Mikhael Bogdanov
63b115abb6 Workaround for KT-34656: temporary disable assertion 2019-10-29 09:48:49 +01:00
pyos
847e287bd6 JVM_IR: add $assertionsDisabled when an inlined function uses it
NOTE: jvmCrossinlineLambdaDeclarationSite.kt is muted because the
inliner does not remap references to an anonymous object's parent
class after regenerating it. Unlike the JVM backend, JVM_IR uses the
top level named class' assertion status for all inner classes. (The
test used to pass because the lambda in `inline fun call` read the
`$assertionsDisabled` field of `CrossinlineLambdaContainer`, which
was not reloaded after changing the assertion status of package `test`.)
2019-10-21 21:05:18 +03:00
pyos
d3992826e4 JVM_IR: discard parameter annotations in anonymous object constructors 2019-10-14 14:54:44 +02:00
pyos
bc4be53569 JVM: generate $assertionsDisabled before inlining the node
This fixes the problem where compiling a class initializer that contains
a call to an `assert`ing function in a separate module causes the
assertion to always be enabled (i.e. the attached test used to fail in
CompileKotlinAgainstInlineKotlin mode).
2019-10-11 14:54:52 +03:00
pyos
06c00f4d9e Unmute some JVM_IR inlining tests 2019-10-08 17:19:41 +02:00
pyos
cea69e0706 JVM_IR: do not generate redundant load+stores before inline calls 2019-10-08 17:19:41 +02:00
pyos
07bde889b4 JVM_IR: generate more correct names for regenerated objects
and fake lambda types, too. (But those only matter for debugging.)

Also, share object name generators between methods with the same name to
avoid rewriting objects from one with objects from the other.
2019-10-08 17:19:41 +02:00
pyos
cd47c11efd Generate unique parameter names in LocalDeclarationsLowering 2019-10-07 15:14:48 +02:00
Georgy Bronnikov
4b5877f3b5 JVM_IR, codegen: handle names for classes within local classes 2019-10-03 17:11:48 +03:00
pyos
ea56a5e8b1 Unmute some JVM_IR inlining tests 2019-10-02 14:48:05 +02:00
Ilmir Usmanov
08794d17a0 Do not box function argument if it is used in EXACTLY_ONCE lambda
Since we cannot change type of parameter, we cannot replace it with
box type.
 #KT-29510 Fixed
 #KT-29614 Fixed
 #KT-29385 Fixed
2019-09-30 17:42:17 +03:00
Steven Schäfer
e4609a9968 JVM IR: Cache inline class replacements at the module level 2019-09-20 23:41:39 +02:00
Alexander Udalov
a7b984bcbf JVM IR: fix generation of generic multi-file delegates 2019-09-19 22:23:16 +02:00
Ilmir Usmanov
63f6d515bc JVM_IR: Generate correct invoke of numbered suspend lambda
Instead of continuation type as last parameter's type, generate Object
type.
2019-09-19 19:28:05 +03:00
Ilmir Usmanov
0e3f0c98e5 JVM_IR: Support inline suspend lambdas 2019-09-17 19:19:27 +03:00
Ilmir Usmanov
1951ff8054 JVM_IR: Minor. Unmute tests 2019-09-16 16:49:24 +03:00
Ilmir Usmanov
402a77126f JVM_IR: Support inline suspend functions
Only no state-machine version for now.
2019-09-16 16:49:21 +03:00
Alexander Udalov
bd8ea9412d JVM IR: implement MethodSignatureMapper.mapFunctionName directly 2019-09-16 14:57:20 +02:00
Georgy Bronnikov
7ede26e8f4 IrCompileKotlinAgainstInlineKotlin tests 2019-09-06 09:19:57 +03:00