Compare commits

...

289 Commits

Author SHA1 Message Date
Svyatoslav Scherbina
99b395b0fa WIP: support Native binary options in Gradle 2021-08-18 18:37:35 +03:00
Svyatoslav Scherbina
0c5bf63844 Native: use binary options machinery for memory model
Old compiler flag (-memory-model) will work too.
2021-08-18 18:29:22 +03:00
Svyatoslav Scherbina
fd7c4c0c2d Native: use binary options machinery for runtime assertions mode 2021-08-18 18:28:19 +03:00
Svyatoslav Scherbina
4a62466671 Native: introduce binary options machinery 2021-08-18 18:27:30 +03:00
pyos
47d0211370 FE: do not enhance ? in jspecify NullMarked scope
No clue whether this should be done for `@TypeQualifierDefault` since it
appears to have no specification whatsoever.

 #KT-48262 Fixed
2021-08-18 16:41:00 +03:00
Jinseong Jeon
5819959cce Consolidate arrayOf call names 2021-08-18 16:04:36 +03:00
Andrey Zinovyev
1cd321a90f [FIR] Add INAPPLICABLE_OPERATOR_MODIFIER diagnostic 2021-08-18 16:03:01 +03:00
Ilya Goncharov
16f41bd80c [Gradle, JS] Use webpack-dev-server rc.1 2021-08-18 15:50:38 +03:00
Mikhael Bogdanov
8ab546ba51 [FIR]: Pass special origins for local functions (named and anonymous) 2021-08-18 09:58:27 +00:00
Mikhael Bogdanov
a5e59e09ee Copy methods for lambdas to DefaultImpls without receiver transformation
#KT-48230 Fixed
2021-08-18 09:58:27 +00:00
pyos
6d7eb2bd21 Add test for KT-48230 2021-08-18 09:58:27 +00:00
Sebastian Sellmair
21f7e16ee6 [Gradle] NativeDistributionCommonizationCache: Acquire FileLock
A `.lock` file will be acquired before running the native
distribution commonizer. This is done to protect data corruption
when multiple process try to commonize at the same time.

This could happen when e.g. two new projects are opened that
both trigger the commonizer during syncing.

^KT-46343 Verification Pending
2021-08-18 09:22:46 +00:00
Tianyu Geng
fb1eac0985 FIR: report SMARTCAST_IMPOSSIBLE on inherited alien properties [KT-48101] 2021-08-18 12:02:02 +03:00
Mikhail Glukhikh
0a6e51e47f FirJavaGenericVarianceViolationTypeChecker: make code a bit more clear 2021-08-18 12:02:01 +03:00
Ilya Goncharov
f37d880964 [Gradle, JS] Add test on valid of webpack config
^KT-48273 fixed
2021-08-18 11:56:19 +03:00
Ivan Kochurkin
301f446433 Restore KtModifierKeywordToken instead of String in modifier diagnostics
Remove KeywordType
2021-08-18 00:45:57 +03:00
Denis.Zharkov
a8077aebb0 FIR: Ignore suspicious test on StrictJavaNullabilityAssertions
^KT-48302 Open
2021-08-17 21:38:01 +03:00
Denis.Zharkov
753ba99b04 FIR: Support enhanced types when checking if Java type is primitive 2021-08-17 21:38:01 +03:00
Denis.Zharkov
a0553f4dfd FIR: Do not build synthetic property named with first capital character 2021-08-17 21:38:01 +03:00
Denis.Zharkov
c3a327e118 FIR: Fix ambiguity on Int2IntMap in IC 2021-08-17 21:38:01 +03:00
Mikhail Glukhikh
1a5552bef8 FIR2IR: fix argument mapping for deserialized annotation #KT-48298 Fixed 2021-08-17 18:22:33 +03:00
Mikhail Glukhikh
6660c9b26b FIR: add test repeating a problem with annotation mapping (KT-48298) 2021-08-17 18:22:33 +03:00
Andrey Zinovyev
ab158a53c3 [FIR] ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION diag 2021-08-17 16:05:42 +03:00
Andrey Zinovyev
1cdbbad367 [FIR] ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION diag 2021-08-17 16:05:42 +03:00
Nikita Bobko
5e87d753b7 Fix coop-dev project import 2021-08-17 13:55:36 +02:00
Ilya Goncharov
a7cc275c7d [Gradle, JS] Update webpack-dev-server
^KT-48273 fixed
2021-08-17 14:44:29 +03:00
Elena Lepilkina
12d694de46 [K/N] Added returns before building DFG 2021-08-17 16:14:07 +05:00
Igor Chevdar
16f0ba8e46 [K/N][optmz] Reworked a bit work with fields 2021-08-17 16:14:07 +05:00
pyos
49c412b022 JVM_IR: implement view caching in kotlin-android-extensions
#KT-47733 Fixed
2021-08-17 13:46:26 +03:00
Pavel Punegov
6ea2dea28e Fix JDK 16 and 17 env variables to correspond to the TC 2021-08-17 09:51:53 +00:00
Yahor Berdnikau
e7a08b14e3 Fix 'jvmTarget' is not updated on reusing configuration cache.
Before this change 'kotlinOptions.jvmTarget' was updated
on 'providedJvm' property value calculation, but, as configuration
cache reuses property value from the cache - 'jvmTarget' update does not
 happen.

This change adds additional call to set 'jvmTarget' on task execution
 phase to ensure even on configuration cache reuse field is set
 to correct value. Update is based whether 'providedJvm' property is set
 or not.

^KT-48226 Fixed
2021-08-17 09:13:29 +00:00
Pavel Punegov
7e1c776376 [Native][tests] Fix warnings in debugger tests 2021-08-17 08:42:11 +00:00
Dmitriy Dolovov
4049cf94b1 [Gradle][Native] Mute BuildCacheRelocationIT.testRelocation on MinGW 2021-08-17 11:01:08 +03:00
Dmitriy Dolovov
da72f26d94 [IR][Tests] Unmute NativeIrLinkerIssuesIT (as far as K/N version is already updated)
^KT-44626
2021-08-17 07:53:47 +00:00
Dmitriy Dolovov
e18c3517a9 [Gradle] Advance K/N version to 1.6.0-dev-2972 2021-08-17 07:53:46 +00:00
Dmitriy Dolovov
cd08dc49a0 [IR][Tests] Mute NativeIrLinkerIssuesIT until K/N version is updated
^KT-44626
2021-08-17 07:53:46 +00:00
Dmitriy Dolovov
4edc1239ac [IR] Use only ASCII-printable chars in IR linker error reports
^KT-44626
2021-08-17 07:53:46 +00:00
Dmitriy Dolovov
af12d61388 [IR] Enhance error reporting for IR linking issues
^KT-44626

Support correct error reporting both with native static caches and without native static caches.
2021-08-17 07:53:45 +00:00
Dmitriy Dolovov
3cd43dced4 [IR] Fix tests for IR linking error reporting
- Run "ktor 1_5_4 and coroutines 1_5_0-RC-native-mt (KT-46697)" test only on Mac host
- Fix application entry point function FQN
- Use OS-neutral URI for configuration of local Maven repos instead of OS-specific path

^KT-44626
2021-08-17 07:53:45 +00:00
Andrey Zinovyev
a17a61341b [FIR] Fix false positive NON_INTERNAL_PUBLISHED_API on constructor val
#KT-48234 Fixed
2021-08-16 19:12:31 +03:00
Tianyu Geng
68f14fdd87 FIR: PrimitiveTypes -> StandardTypes 2021-08-16 16:54:33 +03:00
Tianyu Geng
5a26e79b08 FIR checker: move JAVA_TYPE_MISMATCH to FirJvmErrors 2021-08-16 16:54:32 +03:00
Tianyu Geng
b77dc4136b FIR checker: fix JAVA_TYPE_MISMATCH again 2021-08-16 16:54:22 +03:00
Tianyu Geng
64ebddcbc6 FIR checker: add convention check for ++ and +=, etc 2021-08-16 15:14:30 +03:00
sebastian.sellmair
68e7476765 [Commonizer] ClassSuperTypeCommonizer: Don't find consumed TypeNodes
This commit will also add some simple documentation
to this class and its implementation.

^KT-47430
2021-08-16 10:44:04 +00:00
sebastian.sellmair
1e95717b8d [Commonizer] Implement SimpleCirSupertypesResolverTest
^KT-47430
2021-08-16 10:44:03 +00:00
sebastian.sellmair
f64a0efa8b [Commonizer] Respect artificial supertypes when loading dependencies
CirProvided.ExportedForwardDeclarationClass will now correctly
report artificial superclasses.

The InlineTypeAliasCirNodeTransformer does not need to know anything
about artificial supertypes anymore. When inlining any
type alias, it is enough to resolve the type-alias's expansions
supertypes.

^KT-47430
2021-08-16 10:44:03 +00:00
sebastian.sellmair
26ede5d885 [Commonizer] Add small documentation on CirSupertypesResolver
^KT-47430
2021-08-16 10:44:03 +00:00
sebastian.sellmair
9fb41b6334 [Commonizer] CirKnownClassifiers: Store indices and target dependencies as 'TargetDependent'
^KT-47430
2021-08-16 10:44:02 +00:00
sebastian.sellmair
367db345a8 [Commonizer] Do not re-calculate classifier indices for transformer
^KT-47430
2021-08-16 10:44:02 +00:00
sebastian.sellmair
dda9bb93f6 [Commonizer] Consider exportForwardDeclarations as dependency
This will make follow-up commits easier:
forward declarations are closer to dependencies than being part
of the library. They will be used in the module, bot not
directly provided.

This commit also enables tracking of provided dependency classifiers
in the CirTreeRoot and CirRootNode

^KT-47430
2021-08-16 10:44:01 +00:00
sebastian.sellmair
3d4e861f05 [Commonizer] ModulesProvider: refactor 'loadModuleInfos()' to property
This is done to signal that accessing this data is indeed lightweight.

^KT-47430
2021-08-16 10:44:01 +00:00
sebastian.sellmair
6c246738a5 [Commonizer] TargetDependent: Support index based access
^KT-47430
2021-08-16 10:44:01 +00:00
sebastian.sellmair
dff392f2cd [Commonizer] ClassSuperTypeCommonizer: Include transitive supertypes
This commit still has some left-over todos that shall be done
in a separate commit.

TODOs:
- CirClassifierIndex is calculated once too often
- Reconsider position of classifierIndices in 'CirKnownClassifiers'
- Add documentation/description to complicated 'ClassSuperTypeCommonizer'
- Add documentation/description to CirSupertypesResolver

^KT-47430 Verification Pending
2021-08-16 10:44:00 +00:00
sebastian.sellmair
1857096071 [Commonizer] Implement ClassSuperTypeCommonizer
This implementation runs as regular part of the commonization.
Previous implementation inside the CommonizationVisitor was fully
replaced by it.

As a side effect: CirClass.supertypes was now marked immutable.

^KT-47430 In Progress
2021-08-16 10:44:00 +00:00
sebastian.sellmair
50a343f91e [Commonizer] Deserialize supertypes from provided dependencies
^KT-47430 In Progress
2021-08-16 10:43:59 +00:00
sebastian.sellmair
cdfe8d60a4 [Commonizer] InlineTypeAliasCirNodeTransformer: add artificial supertypes
When inlining any TypeAlias pointing towards forward declarations,
the inlined class will respect implicit supertypes.

This logic is analog to
KlibResolvedModuleDescriptorsFactoryImpl.createForwardDeclarationsModule

^KT-47430 In Progress
2021-08-16 10:43:59 +00:00
Sergey Bogolepov
0c35a3b699 [K/N] A bit cleaner reflection of code coverage state in docs. 2021-08-16 09:22:32 +00:00
Ilmir Usmanov
486c6b3c15 Remove obsolete experimental coroutines support
in compiler.
2021-08-13 22:31:30 +02:00
Ilmir Usmanov
ebb340fe68 Do not just merge consequent LVT ranges, but also extend them 2021-08-13 23:12:10 +03:00
Ivan Kochurkin
8d764fa50e [FIR] Add FirPropertyAccessExpression that inherits FirQualifiedAccessExpression 2021-08-13 20:05:43 +03:00
Alexander Udalov
0fb398d45e Build: enable Werror for almost all compileKotlin tasks
The only exception at this point is :kotlin-gradle-plugin:compileKotlin.
2021-08-13 17:46:57 +02:00
Ivan Kochurkin
f2ffead881 Reduce allocations in KotlinTarget and modifier checkers 2021-08-13 18:32:29 +03:00
Ivan Kochurkin
2c1c24c042 [FIR] Implement WRONG_MODIFIER_CONTAINING_DECLARATION, DEPRECATED_MODIFIER_CONTAINING_DECLARATION 2021-08-13 18:32:28 +03:00
Ivan Kochurkin
cd6384eb20 [FIR] Fix handling of WRONG_MODIFIER_TARGET
Implement DEPRECATED_MODIFIER, DEPRECATED_MODIFIER_FOR_TARGET, REDUNDANT_MODIFIER_FOR_TARGET
2021-08-13 18:32:27 +03:00
Ivan Kochurkin
e85940a1ac Unbind modifiers checks from psi
Use common code in FE and FIR in modifier checker, refactor
2021-08-13 18:32:26 +03:00
Dmitry Petrov
ed0e3b0fed JVM_IR KT-47984 minor fixes after review 2021-08-13 18:08:55 +03:00
Dmitry Petrov
f8503ba1bf JVM_IR KT-47984 minor avoid using @Deprecated function in tests 2021-08-13 18:08:55 +03:00
Dmitry Petrov
55663a0fb1 JVM_IR KT-47984 allow only limited list of GETSTATICs in arg loading 2021-08-13 18:08:54 +03:00
Dmitry Petrov
32c51cbb45 JVM_IR KT-47984 minor drop unneeded caching 2021-08-13 18:08:53 +03:00
Dmitry Petrov
15c41b2610 JVM_IR KT-47984 add test for argument reordering 2021-08-13 18:08:52 +03:00
Dmitry Petrov
edd2ca775b JVM_IR KT-47984 use stack size calculator from ASM 2021-08-13 18:08:52 +03:00
Dmitry Petrov
5096e8c5c4 JVM_IR KT-47984 transform inplace arguments before inlining 2021-08-13 18:08:49 +03:00
Dmitry Petrov
7a99f9ff2e JVM_IR KT-47984 allow noinline functional inplace args 2021-08-13 18:08:48 +03:00
Dmitry Petrov
9be941def2 JVM_IR KT-47984 don't move inplace arguments with suspension points 2021-08-13 18:08:47 +03:00
Dmitry Petrov
9acdcc7590 JVM_IR KT-47984 minor cleanup 2021-08-13 18:08:47 +03:00
Dmitry Petrov
bf362abb57 JVM_IR KT-47984 update LVT entries for transformed instructions 2021-08-13 18:08:46 +03:00
Dmitry Petrov
6b18f33f92 JVM_IR KT-47984 don't transform calls with non-local jumps in arguments 2021-08-13 18:08:45 +03:00
Dmitry Petrov
b01c13a4df JVM_IR KT-47984 inplace arguments inlining for @InlineOnly functions 2021-08-13 18:08:44 +03:00
Dmitry Petrov
ec90649854 JVM_IR minor cleanup in inliner 2021-08-13 18:08:43 +03:00
Pavel Kunyavskiy
d88a665fa8 [K/N] Implement Lazy for new mm 2021-08-13 13:20:59 +00:00
Ivan Kylchik
2f2e608502 Expand the possibilities of object's interpretation
It is possible to create object in interpreter even if its
receiver symbol came from function parameter instead of object's class.
#KT-48174 Fixed
2021-08-13 16:18:36 +03:00
Ivan Kylchik
492b8acf93 Rename some methods in interpreter's stack to make their purpose clearer 2021-08-13 16:18:34 +03:00
Ivan Kylchik
69fe7e66a5 Introduce some helpful type aliases in interpreter 2021-08-13 16:18:32 +03:00
Ivan Kylchik
1808f14677 Switch from using of MutableList to ArrayDeque in interpreter's stack 2021-08-13 16:18:32 +03:00
Ivan Kylchik
ac2dffa74e Speed up interpreter's stack by using map of variables instead of list 2021-08-13 16:18:31 +03:00
Ivan Kylchik
a630273af2 Speed up interpreter's intrinsic check by introducing map of handlers 2021-08-13 16:18:30 +03:00
Ivan Kylchik
bc9b2fd78b Uncomment some test cases in reflection test data for interpreter 2021-08-13 16:18:29 +03:00
Ivan Kylchik
23b315446f Support sam conversion in ir interpreter 2021-08-13 16:18:28 +03:00
Ivan Kylchik
b85a796492 Support interpretation for floorDiv and mod functions 2021-08-13 16:18:28 +03:00
Ivan Kylchik
f9607292b5 Add additional useful ir classes into IrInterpreterEnvironment 2021-08-13 16:18:26 +03:00
Ivan Kylchik
b46a42be33 Drop toIrConst function with IrBuiltIns parameter 2021-08-13 16:18:25 +03:00
Pavel Kunyavskiy
7bddc2a815 [K/N] Add new exception for CallsChecker 2021-08-13 13:12:21 +00:00
Mikhail Glukhikh
4e4d36f85a FIR: take lower priority into account during references EagerResolve
#KT-48158 Fixed
2021-08-13 11:14:04 +03:00
Mikhail Glukhikh
a21d281c19 FIR: fix capturing on intersection types #KT-48109 Fixed 2021-08-13 11:14:03 +03:00
Mikhail Glukhikh
a04913a197 FIR: use captureFromTypeParameterUpperBoundIfNeeded for argument types
#KT-48161 Fixed
2021-08-13 11:14:02 +03:00
Mikhail Glukhikh
73a8b4544a FIR: don't report EQUALITY_NOT_APPLICABLE for classes from java.*
Workaround for KT-48113
2021-08-13 11:14:01 +03:00
Mikhail Glukhikh
b617aca8ee FIR: fix scope order for super-type resolve #KT-48159 Fixed 2021-08-13 11:14:01 +03:00
Mikhail Glukhikh
ca98417a0c FIR: add test for erroneous type inference in UAST (KT-48159) 2021-08-13 11:14:00 +03:00
Mikhail Glukhikh
b1bcbaf48f FirConstChecks: support "Some string".length case properly
#KT-48165 Fixed
2021-08-13 11:13:59 +03:00
Mikhail Glukhikh
f6413c41a0 FIR: fix serialization of JvmField-properties of local classes
#KT-48175 Fixed
2021-08-13 11:13:58 +03:00
Mikhail Glukhikh
2e2edf398c FIR: consider enum class overridden members non-final #KT-48164 Fixed 2021-08-13 11:13:57 +03:00
Nikolay Krasko
8e32bbbe90 Clean up 203.8084.24 dependencies a bit 2021-08-12 21:15:32 +03:00
Nikolay Krasko
23c438aa03 Clean up 203.6682.168 dependencies 2021-08-12 21:15:31 +03:00
Nikolay Krasko
63d1e195e0 Clean up 202.7660.26 dependencies 2021-08-12 21:15:31 +03:00
Nikolay Krasko
9e0ba8c3d2 Clean up 193.6494.7 mentionings 2021-08-12 21:15:30 +03:00
Nikolay Krasko
c56b6455f1 Clean up 202.7660.3 mentionings 2021-08-12 21:15:29 +03:00
Igor Yakovlev
9b9a529b7f Reflect addition of new 'kotlin.jvm-run-configurations' module in Gradle 2021-08-12 18:16:00 +02:00
Ivan Kochurkin
d346953de9 [FIR] Move FirCommaInWhenConditionChecker to syntax subdirectory 2021-08-12 18:42:26 +03:00
Tianyu Geng
1679da45ab FIR checker: COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT
FIR simply ignores anything after the first comma if the when expression
doesn't have a subject. Hence, the checker has to rely on PSI structure
instead.
2021-08-12 18:42:26 +03:00
Sergey Bogolepov
db12a96e54 Fix test that was broken by e159392d by disabling native caches. 2021-08-12 18:02:23 +03:00
Ting-Yuan Huang
39c6be86cb K2JsIrCompiler: pass right configuration when creating lib module 2021-08-12 18:01:59 +03:00
Ting-Yuan Huang
06d3c6f233 Support repeated analysis and frontend-only-mode in K2JsIrCompiler 2021-08-12 18:01:58 +03:00
Ting-Yuan Huang
e75ca75e3e K2JsIrCompiler: hoist common front-end preparation logic
Instead of creating ModuleStructure and run analysis in each backend,
the common preparation logic is moved into K2JsIrCompiler.doExecute().
2021-08-12 18:01:56 +03:00
Igor Laevsky
94af3adb4b WASM: Disable flaky test 2021-08-12 17:32:35 +03:00
Alexander Udalov
1b98723b3f JVM IR: fix incorrect detection of interface method impls in Java
The problem in the test case was that `JImpl.entrySet` was detected by
ReplaceDefaultImplsOverriddenSymbols as a class fake override, which
overrides non-abstract interface method. Thus, overriddenSymbols of
`MyMap.entrySet` were changed in
`ReplaceDefaultImplsOverriddenSymbols.visitSimpleFunction`.

Later, BridgeLowering tried to determine which special bridges to
generate for `MyMap.<get-entries>`, and for that it inspected existing
methods and their overrides.

Normally we would generate the following special bridge:

    getEntries()Ljava/util/Set;
        invokespecial JImpl.entrySet()Ljava/util/Set;

However, because of incorrect overrides, the generated class method was
selected here instead of the expected `Map.<get-entries>`:
06001fc091/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt (L282)
and since the JVM signature of the generated class method is the same as
that of the fake override in MyMap, we never got to generating the
special bridge.

The solution is to skip Java classes when looking for class methods
which override non-abstract interface methods. This logic only makes
sense for Kotlin code, because only Kotlin has DefaultImpls, and the
requirement to generate non-abstract fake overrides of interface methods
as actual methods in the bytecode, delegating to DefaultImpls.

 #KT-48167 Fixed
2021-08-12 13:51:33 +02:00
Alexander Udalov
d124239025 JVM IR: do not attempt to mangle function expressions
For some reasons, lambdas and function expressions are represented
slightly differently in psi2ir. Lambdas are translated to a block with a
function of origin LOCAL_FUNCTION_FOR_LAMBDA and name "<anonymous>", but
function expressions are translated to a block with DEFINED function
"<no name provided>".

Tweak the condition for detecting local functions a bit, to avoid
similar situation in the future if we add some other origins for local
functions.

 #KT-48207 Fixed
2021-08-12 13:50:23 +02:00
Mikhail Glukhikh
dd3eb53904 Drop forgotten foreign annotation test data 2021-08-12 14:25:18 +03:00
Yahor Berdnikau
3acb96e474 Allow running KotlinJavaToolchainTest on any user JDK. 2021-08-12 10:00:23 +02:00
Bingran
c57302abba Only check ExternalDependency when customizing kotlin dependencies
This commit fixes the issue where kgp checks group/version of project
dependencies which is uncompatible with project isolation. With this
change, kgp will only check ExternalDependency which should be enough
for setting up kotlin dependencies.

This change also changes the way we apply cache redirector gradle
files to all projects when setting up test projects. To make it
compatible with project isolation, we should move away from using
project.getAllProjects() function.

^KT-47792 Fixed
Test: existing + SimpleKotlinGradleIT.testProjectIsolation
2021-08-12 09:51:20 +02:00
Andrey Zinovyev
1338675833 [FIR] Fix while's label, when condition has lambda
#KT-48116 Fixed
2021-08-12 10:20:45 +03:00
Alexander Shabalin
06001fc091 [K/N] Tweak fronted warning messages for the new MM 2021-08-11 20:06:19 +00:00
Andrey Zinovyev
d3905fd763 Add dist dependency for tests
Because some tests require stdlib
2021-08-11 21:57:16 +03:00
Andrey Zinovyev
3ec9599bc4 [FIR][CFG] Partial support of postponed Nothing calls
In try blocks, last call won't be completed when building node for it
This is workaround to partially reconstruct nothing stub node for such
calls. Should work for non-local returns in try only.
#KT-48160 Fixed
2021-08-11 21:57:14 +03:00
Ivan Kochurkin
445e5122c1 [FIR] Fix conversion of underscored value parameters in functions
Fix false REDECLARATION
2021-08-11 21:52:46 +03:00
Ilya Kirillov
ebe96ec79a FIR IDE: fix reference resolve with invalid number of type args 2021-08-11 18:09:05 +02:00
Ilya Kirillov
a8f7bf5fbc HL API: cleanup reference resolve testdata 2021-08-11 18:09:05 +02:00
Ilya Kirillov
2e3b576342 FIR IDE: change destructing declaration reference behaviour to match FE1.0 plugin behaviour 2021-08-11 18:09:05 +02:00
Pavel Punegov
aef45f0997 [Native] Exclude on wasm initializers tests.
Tests use exceptions and workers that are not supported in wasm
2021-08-11 13:56:48 +00:00
Pavel Punegov
d7f5015faa [Native] wasm: use JS pow method
Replace usage of C pow() function with JS to fix the issue
with stack overflow caused by invocation of missing pow function
2021-08-11 13:56:47 +00:00
Pavel Punegov
cd487efbe9 [Native][test] Exclude FP parsing tests that require exceptions on WASM 2021-08-11 13:56:47 +00:00
pyos
623b289616 Regenerate foreign annotation test data for FIR 2021-08-11 15:58:02 +03:00
pyos
58110709f3 Get rid of lambdas in AbstractForeignAnnotationsTestBase
Also enable the features from the previous two commits
2021-08-11 15:58:01 +03:00
pyos
28c473074c Permit overriding the FIR test in FirTestDataConsistencyHandler 2021-08-11 15:58:01 +03:00
pyos
cd26ef2bb5 Add FIR version of JspecifyDiagnosticComplianceHandler 2021-08-11 15:58:01 +03:00
Mads Ager
608b88996a [JVM_IR] Fix inlining of callable references to extension methods.
Check directly that the referenced function is an extension
function instead of relying on the annotation on the type.

^ KT-47988 Fixed.
2021-08-11 13:29:11 +02:00
Mikhael Bogdanov
1760befa37 [KAPT] Add experimental JDK 17 support
#KT-47583 Fixed
2021-08-11 10:05:24 +02:00
Igor Chevdar
81ce59cf48 [K/N][IR][codegen] Implemented eager initialization
Properties marked with @EagerInitialization will be initialized at program/worker start
even in lazy initialization mode
2021-08-11 11:53:19 +05:00
Sergey Bogolepov
e159392d22 [K/N] Enable caches for iosArm64 and linuxX64 by default 2021-08-11 06:38:59 +00:00
Nikita Bobko
5455800de4 [imltogradle] Exclude 'kotlin.util.compiler-dependencies' module from generation
This module is used as helper module in JPS project module to make sure that IDEA will download
all required dependencies. There are some dependencies which IDEA cannot determine as used so
we force it to download them (kotlinc.kotlin-dist, kotlinc.kotlin-compiler-testdata)

We don't need this module in Gradle project model

This commit fixes:
```
Could not resolve project :prepare:ide-plugin-dependencies:kotlin-compiler-testdata-for-ide.
Required by:
    project :kotlin-ide.kotlin.util.compiler-dependencies
```
2021-08-11 02:17:52 +02:00
Nikita Bobko
747cc7d55d [imltogradle] Fix other kotlinc libraries which don't follow kotlinc.* naming
e.g. kotlin-reflect
2021-08-11 02:17:51 +02:00
Nikita Bobko
784273ac5b [imltogradle] Add additional check for absence of snapshot version in JpsLikeJarDependency 2021-08-11 02:17:51 +02:00
Nikita Bobko
493fdbd418 Fix kotlin stdlib handling for 212 IDEA in ide-iml-to-gradle-generator 2021-08-11 02:17:51 +02:00
Nikita Bobko
8ad368e990 Update verification-metadata.xml with 212.4746.92 artifacts 2021-08-11 02:17:50 +02:00
Ilya Goncharov
40d19b50c5 [Gradle, JS] Use Gradle's hashers 2021-08-10 18:45:09 +00:00
Ilya Goncharov
bfcd954dd3 [Gradle, JS] Add test on not updating Node.JS if it was downloaded
^KT-47845 fixed
2021-08-10 18:45:09 +00:00
Ilya Goncharov
b8330deefa [Gradle, JS] Consider potential hash of nodejs and yarn
^KT-47845 fixed
2021-08-10 18:45:08 +00:00
Ilya Goncharov
5ec19c2417 [Gradle, JS] Up-to-date checks for Node js and yarn
^KT-47845 fixed
2021-08-10 18:45:08 +00:00
Ilya Kirillov
1a1f6b0c0b Regenerate FirIdeSpecTest 2021-08-10 20:06:36 +02:00
Ilya Kirillov
017448e359 FIR IDE: make KtExpression.getKtType() to return null for non-expressions 2021-08-10 18:58:06 +02:00
Roman Artemev
d3ddeef67f [JS IR] Wrap private top level function with internal accessor stub
In case internal inline function references private top level function
after inline such function (T.L.P.) couldn't be referenced
in klib and IC cache. So create internally visible accessors for P.T.L.
function similar to what JVM backend does.

 - add box test
2021-08-10 19:52:08 +03:00
Roman Artemev
b3dbca7ea6 [JS IC] Fix test runner 2021-08-10 19:52:07 +03:00
Tianyu Geng
06ee84f809 FIR checker: report AMBIGUOUS_SUPER 2021-08-10 19:36:44 +03:00
Ivan Kochurkin
5b9ce7e823 [FIR] Use typeArgumentsList from delegatedTypeRef instead of accessing via tree 2021-08-10 19:36:43 +03:00
Tianyu Geng
280c445783 FIR checker: check super reference
This change touches the following diagnostics to make them behave closer
to FE1.0

* SUPER_NOT_AVAILABLE
* SUPER_IS_NOT_AN_EXPRESSION
* INSTANCE_ACCESS_BEFORE_SUPER_CALL
* NOT_A_SUPERTYPE

Other than tweaking the diagnostics, this change also alters resolution
by consider marking `super` with mismatched type parameter as
errorenous. As a result, the following code no longer resolves.

```
class A: B() {
  fun test() {
    super<String>.length
    //            ^^^^^^ FIR currently resolves this to `String.length`.
    //                   With this change, `length` becomes unresolved
    //                   instead
  }
}
```

Also, now we report `UNRESOLVED_LABEL` on unresolved label on `super`
reference, though FE1.0 reports `UNRESOLVED_REFERENCE`.

All the errors above are reported as ConeDiagnostics and hence some
checkers are deleted.

In addition, it also suppresses more downstream (mostly unresolved)
errors if the receiver has errors. FE1.0 doesn't do it for all the cases
we have here. But it seems nicer to reduce these "redundant" unresolved
errors.
2021-08-10 19:36:43 +03:00
Tianyu Geng
bcf6202863 FIR checker: fix position strategy for UNRESOLVED_LABEL 2021-08-10 19:36:04 +03:00
Tianyu Geng
45d31fdba2 FIR: fix atomic qualified acess sharing the same PSI with callee ref
Consider an atomic reference `i`, it's FIR representation is

- FirQualifiedAccessExpression
  - calleeReference : FirNamedReference

Currently, both of the above FIR elements uses the same PSI element as
the source. Such problems are not present with `this` or `super` because
we manually mark them as `ExplicitThisOrSuperReference`.

This change generalizes the previous `ExplicitThisOrSuperReference` as
`ReferenceInAtomicQualifiedAccess` and fixes it for more cases.
2021-08-10 19:35:19 +03:00
Alexander Udalov
3bc0eaff59 Fix warnings in stdlib samples and test modules 2021-08-10 17:57:50 +02:00
Alexander Udalov
0d1380c232 Fix warnings in generator modules 2021-08-10 17:57:50 +02:00
Ivan Kochurkin
2ca3adbcb2 [FIR] Throw REDECLARATION for duplicated type parameters in declarations 2021-08-10 15:09:27 +00:00
Ivan Kochurkin
c19598c2fc [FIR] Throw REDECLARATION for duplicated enum entries 2021-08-10 15:09:26 +00:00
Ivan Kochurkin
9736cc162b [FIR] Throw REDECLARATION for duplicated value parameters in function
Add new test file
2021-08-10 15:09:26 +00:00
Ivan Kochurkin
fd92b851a2 [FIR] Implement PACKAGE_OR_CLASSIFIER_REDECLARATION
Fix REDECLARATION positioning
2021-08-10 15:09:25 +00:00
Nikolay Krasko
1c678be0d3 Drop 202 bunch support 2021-08-10 15:25:46 +03:00
Dmitriy Dolovov
cfc4e715e4 [IR] Tests for IR linking error reporting
^KT-44626
2021-08-10 14:02:45 +03:00
Dmitriy Dolovov
c1fb40a436 [IR] Enhance error reporting for IR linking issues
^KT-44626

Typical use case:
- There are two KLIB libraries: A and B.
- Library A has two versions: A.v1 (older) and A.v2 (newer).
- A.v2 is ABI-incompatible with A.v1.
- B depends on A and was compiled against A.v1.
- An attempt to build the application with A.v2 and B fails with weird error message. It's unclear for end user what's wrong and what needs to be done to fix the issue.

The fix improves error reporting for the following particular cases:
- A symbol that is gone (KT-41378)
- A class that became a typealias (KT-47285, KT-46697)
- A typealias that became a class (KT-46340)
2021-08-10 14:02:40 +03:00
Dmitriy Dolovov
672b972b38 [Native] Add '-Xexternal-dependencies' CLI parameter to pass external deps
^KT-44626
2021-08-10 14:02:35 +03:00
Dmitriy Dolovov
ac387b1f26 [Gradle, Native] Pass external dependencies to Kotlin/Native link tasks
^KT-44626
2021-08-10 14:02:27 +03:00
Mikhail Glukhikh
2c31d2e67d FirTestDataConsistencyHandler: return back FIR files auto-generation 2021-08-10 13:19:28 +03:00
Mikhail Glukhikh
8c51c3c5c3 FirTestDataConsistencyHandler: fix behavior on Windows (partial revert) 2021-08-10 13:19:27 +03:00
Mikhail Glukhikh
512a851c65 Minor fix of test data for consistency with FIR 2021-08-10 13:19:26 +03:00
Mikhail Glukhikh
85a2a3255d Add new SENSELESS_COMPARISON in FIR foreign annotation tests 2021-08-10 13:19:26 +03:00
pyos
cdc0f36859 Permit silencing FIR tests with results depending on configuration 2021-08-10 13:19:25 +03:00
pyos
33251f6d50 Generate foreign annotation test data for FIR 2021-08-10 13:19:23 +03:00
pyos
5873511f64 Generalize AbstractForeignAnnotationsTestBase to FIR 2021-08-10 13:19:22 +03:00
pyos
e2e0358505 Remove "FIR" foreign annotation tests
They do not actually use FIR.
2021-08-10 13:19:21 +03:00
Tianyu Geng
1607a8231a FIR checker: ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS 2021-08-10 13:02:10 +03:00
Tianyu Geng
927723c766 FIR checker: fix JAVA_TYPE_MISMATCH checker
First, the order of arguments is swapped.
Second, projection erasure for argType was too aggressive. We should
instead retain the projections that are under an invariant position.
2021-08-10 13:00:18 +03:00
Tianyu Geng
cc531149e5 Ignore kotlin-ide directory 2021-08-10 13:00:14 +03:00
Hung Nguyen
eb94167ff2 Move RuntimeModuleData from :core:descriptors.runtime to :core:descriptors.jvm
We are working on a feature in the Kotlin Gradle plugin called
`kotlin.incremental.useClasspathSnapshot` to improve incremental
Kotlin compilation.

To allow reuse when writing this feature, this commit moves most of the
code in RuntimeModuleData (in the ':core:descriptors.runtime' project)
to DeserializationComponentsForJava (in the ':core:descriptors.jvm'
project), so that the API can be accessed from the
':kotlin-gradle-plugin' and ':kotlin-build-common' projects where the
feature is written.

Bug: KT-45777
Test: Existing tests should pass (this is a refactoring-only change)
2021-08-10 12:29:45 +03:00
Hung Nguyen
170184dce4 KT-45777: Refactor RuntimeModuleData to support classpath snapshotting
We are working on a feature in the Kotlin Gradle plugin called
`kotlin.incremental.useClasspathSnapshot` to improve incremental
Kotlin compilation.

In this feature, we need to extract ABI information from a .class file.
If the .class file is a Kotlin class, this info can be found in the
class header data. But if the .class file is a Java class, this info is
not readily available.

The RuntimeModuleData class in the ':core:descriptors.runtime' project
can help with that: It uses reflection to generate `ClassDescriptor`s.

However, reflection requires a full classpath to work correctly, whereas
we want to generate a `ClassDescriptor` directly for each class file
(also, reflection is probably slow).

To address that, this commit refactors RuntimeModuleData so that it can
support a generic Kotlin/JavaClassFinder, which can be based on either
reflection or bytecode analysis. The existing code continues to use
reflection while the new feature will use bytecode analysis (e.g., using
the existing BinaryJavaClass).

Bug: KT-45777
Test: Existing tests should pass (this is a refactoring-only change)
2021-08-10 12:29:44 +03:00
Hung Nguyen
206457d9ff KT-45777: Take snapshots and compute changes for Kotlin classes
Reuse the existing IncrementalJvmCache to take snapshots and compute
changes for Kotlin classes.

Java classes will be handled next.

Bug: KT-45777
Test: New ClasspathSnapshotterTest, ClasspathChangesComputerTest
2021-08-10 12:22:58 +03:00
Alexander Shabalin
7e04bb4bf1 [K/N] Refactor unhandled exception handling API
* Do not reset unhandled exception hook
* Add processUnhandledException to perform default unhandled exception
  processing
* Add terminateWithUnhandledException to report the unhandled exception
  and terminate the program
* Use the default unhandled exception processing in entrypoint, interop
  boundaries and in Worker.executeAfter
* Add -Xworker-exception-handling to control exception processing of
  Worker.executeAfter. By default its the old behaviour with the old MM,
  and new behaviour with the new MM.
2021-08-10 08:22:55 +00:00
Ilya Goncharov
766857881a [JS IR] Review remarks
- Use intrinsic on this
- Enqueue invoke for DCE
- Change transform
- Ignore instead of target backend

^KT-46204 fixed
2021-08-10 07:24:51 +00:00
Ilya Goncharov
2f0f88062a [JS IR] Change global map in context to mapping
^KT-46204 fixed
2021-08-10 07:24:50 +00:00
Ilya Goncharov
a28138eb72 [JS IR] Change js function on Kotlin code
^KT-46204 fixed
2021-08-10 07:24:49 +00:00
Ilya Goncharov
b6c3132614 [JS IR] Ignore test for legacy backend
^KT-46204 fixed
2021-08-10 07:24:49 +00:00
Ilya Goncharov
627af332b1 [JS IR] Use PublishedApi for intrinsic
^KT-46204 fixed
2021-08-10 07:24:48 +00:00
Ilya Goncharov
e6af3ff6a8 [JS IR] Rename and doc new intrinsics, add new intrinsic to call suspend fun as supertype
^KT-46204 fixed
2021-08-10 07:24:48 +00:00
Ilya Goncharov
a70fc99130 [JS IR] Add intrinsic to call suspend functions as super type
^KT-46204 fixed
2021-08-10 07:24:47 +00:00
Ilya Goncharov
22d202e657 [JS IR] Add test on type check of suspend functional interfaces
^KT-46204 fixed
2021-08-10 07:24:47 +00:00
Ilya Goncharov
755f847ab9 [JS IR] Use invoke for coroutines in runtime
^KT-46204 fixed
2021-08-10 07:24:46 +00:00
Ilya Goncharov
3c9dcdbbee [JS IR] Generate suspend function as invoke
[JS IR] Fix type check utils to work with array of arities

[JS IR] Store multiple arities for suspend functional interface implementers

^KT-46204 fixed
2021-08-10 07:24:46 +00:00
Ilya Goncharov
8a812996dd [Frontend, JS] Not report error in for inheritance suspend function interface
^KT-46204 fixed
2021-08-10 07:24:45 +00:00
Georgy Bronnikov
1d913a6bf0 JVM_IR: add test for serialization of raw types 2021-08-10 00:37:46 +03:00
Georgy Bronnikov
3b8cb4b00d ModuleTransformerForTwoFilesBoxTests -> SplittingModuleTransformerForBoxTests
Need to include Java files in IR serialization tests, so generalize
TwoFilesBoxTest for more than two files.
2021-08-10 00:37:44 +03:00
Georgy Bronnikov
13cf9329b2 IR: always serialize constant initializers for fields. 2021-08-10 00:37:42 +03:00
Georgy Bronnikov
7e71bd8f1c Add module dependency to fir/checkers/checkers-component-generator
This is a transitive dependency needed when bootstrapping in
-Xserialize-ir mode.
2021-08-10 00:37:41 +03:00
Georgy Bronnikov
307de0be89 IR: always update deserializedSymbols in referenceLocalIrSymbol
The symbol created in deserializeIrSymbolToDeclare might be discarded
when an existing declaration is used in deserialization (as it happens
when deserializing IR bodies for JVM declarations).
2021-08-10 00:37:37 +03:00
Georgy Bronnikov
eccbf38061 IR: use existing type parameters when deserializing IR 2021-08-10 00:37:36 +03:00
Georgy Bronnikov
fb801bdc33 IR: fix mangling of toplevel properties 2021-08-10 00:37:36 +03:00
Georgy Bronnikov
54957ead5c JVM_IR: add test for signatures of flexible types 2021-08-10 00:37:27 +03:00
Georgy Bronnikov
1d2d1f9e8d IR: change mangling for flexible types in DescriptorMangleComputer
This reverts commit 4af2aaedb1.
2021-08-10 00:37:24 +03:00
Alexander Udalov
afacff326d JVM IR: fix smart cast on argument of 'throw'
#KT-48163 Fixed
2021-08-09 22:34:44 +02:00
Ilya Kirillov
cb37a05b79 Restore LC compiler testdata 2021-08-09 20:29:22 +02:00
Jinseong Jeon
e64f7ffb98 FIR LC: populate ctor in anonymous objects
Note that enum entries are modeled as anonymous objects in FIR too.
2021-08-09 20:29:20 +02:00
Jinseong Jeon
75c76e2b57 FIR IDE: resolve implicit ctor delegation calls 2021-08-09 20:29:19 +02:00
Jinseong Jeon
f7f51cf38e FIR IDE: allow implicit ctor call for psi retrieval 2021-08-09 20:29:19 +02:00
Jinseong Jeon
4396482fed FIR IDE: fix nullability of KtType variants 2021-08-09 20:29:19 +02:00
Jinseong Jeon
46a0c4be4b FIR LC: populate property from primary ctor later 2021-08-09 20:29:18 +02:00
Jinseong Jeon
fba480875f FIR LC: populate constructors after member methods 2021-08-09 20:29:18 +02:00
Jinseong Jeon
edc134ef2d FIR IDE: drop stale test results in kt files 2021-08-09 20:29:17 +02:00
Jinseong Jeon
ba8f2e6bf3 FIR LC: introduce FirLightParameterList
LightParameterListBuilder, as a subtype of PsiParameterList, is good
enough for LightMethod's parameter list abstraction. However, it does
not have a parent link, which bothers upward conversion in UAST
(a.k.a. convertParent APIs). So we need an abstraction similar to
KtLightParameterList (in FE 1.0 LC).
2021-08-09 20:29:17 +02:00
Ivan Kochurkin
c1afb6354b [FIR] Restore UPPER_BOUND_VIOLATED and TYPE_VARIANCE_CONFLICT as errors, fix TestStep.kt 2021-08-09 18:19:58 +03:00
Viacheslav Kormushkin
d670743a2f Cocoapods plugin: error reporting in case CocoaPods is not installed on users machine
#KT-47362
2021-08-09 12:54:29 +00:00
Andrey Zinovyev
1b81018b69 [FIR] Fix overloading of renamed jvm methods
#KT-48102 Fixed
2021-08-09 15:22:06 +03:00
Tianyu Geng
cd99c35649 FIR: instantiate type argument to captured type if needed 2021-08-09 14:38:30 +03:00
Tianyu Geng
bcf6582af7 FIR checker: make TypeApproximatorConfiguration.capturedType consistent with others 2021-08-09 14:38:30 +03:00
Tianyu Geng
758859f198 FIR checker: report JAVA_TYPE_MISMATCH 2021-08-09 14:38:29 +03:00
sebastian.sellmair
eec5f99e35 [Gradle] Support 'KONAN_DATA_DIR' in Commonizer tests 2021-08-09 09:48:44 +00:00
sebastian.sellmair
552a012e65 [Gradle] Add missing mavenCentral repository to test projects 2021-08-09 09:48:44 +00:00
sebastian.sellmair
3625c953ae [Gradle] CInteropCommonizerDependent: Implement 'fromAssociateCompilations'
This additional API and changes in CInteropCommonizerDependencies.kt
will make sure, that test source sets will still receive commonization
results, even when the exact targets are not requested by
any of the main source sets.

^KT-48138 Verification Pending
2021-08-09 09:48:43 +00:00
sebastian.sellmair
9a39b1f4d1 [Gradle] Implement integration test to cover ^KT-48138 2021-08-09 09:48:43 +00:00
sebastian.sellmair
c07dcb27df [Gradle] CommonizerIT: Add assertion on commonMain when jvm target is present 2021-08-09 09:48:42 +00:00
sebastian.sellmair
5485a6d6cd [Gradle] CInteropCommonizerDependent: Drop bad condition on compilations
The dropped condition is bad, since source sets like 'commonMain'
might still participate in a 'compileKotlinMetadata' task,
which is not a shared native compilation.

It is absolutely okay to just rely on the return of
'getCommonizerTarget': If a shared commonizer target is returned,
then the source set is guaranteed to be a shared native source set.

^KT-48118 Verification Pending
2021-08-09 09:48:42 +00:00
sebastian.sellmair
b1c5c10233 [Gradle] Implement test KT-48118 c-interops available in commonMain
Integration Test project was taken from:
https://github.com/4qa/kotlin-multiplatform-issues/tree/cinterop-common

The issue seems to be twofold:
1) The old `compileKotlinMetadata` task is still found, even
when compatibilityMetadataVariant is disabled

2) The shared native compilation for commonMain can't be found, because
it is not listing its default source set:
(see: https://youtrack.jetbrains.com/issue/KT-45412)

Covers ^KT-48118
2021-08-09 09:48:42 +00:00
Mikhail Glukhikh
37d25a58e8 Fix .gitignore (intellij directory) 2021-08-09 10:00:24 +03:00
Ilya Matveev
6c7f04ffc6 [K/N][tests] Fix disabling stress_gc_allocations for No-op GC 2021-08-07 06:28:50 +00:00
Nikita Bobko
a97b4ea4ae Fix UnsupportedClassVersionError when running ./gradlew generateIdePluginGradleFiles
This commit fixes:
```
Exception in thread "main" java.lang.UnsupportedClassVersionError: com/intellij/jps/impl/JpsIdePluginManagerImpl has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
```
2021-08-07 00:07:30 +03:00
Nikita Bobko
dac4fe7507 Adapt coop-dev for 212 platform 2021-08-07 00:07:28 +03:00
Alexander Dudinsky
3d81eba32b New HMPP import and highlighting tests
New tests `testHmppLibAndConsumer` and `testMultiModulesHmpp` were added
The first is a test with MPP library and its consumers, it checks import
and also highlighting before and after the library was published
The second is a project which contains three multiplatform modules and
two platform modules and checks import and highlighting.

Original commit: 15582b0353
2021-08-07 00:07:27 +03:00
Alexander Udalov
bc5a79ffcc Minor, add test on repeatable annotations on property getters
#KT-14392
 #KT-36476
2021-08-06 22:47:44 +02:00
Alexander Udalov
209c0fe819 Revert "[Test] Temporary mute some tests because of problems with RepeatedAnnotationLowering"
This reverts commit 3a210f6c81.
2021-08-06 22:47:44 +02:00
Alexander Udalov
f8af127a4e Do not load Java @Repeatable for Kotlin-repeatable annotations
#KT-48131 Fixed
2021-08-06 22:47:36 +02:00
Alexander Udalov
89b3013294 Build: enable Werror for all compileJava tasks 2021-08-06 22:37:00 +02:00
Alexander Udalov
c821aba3bd Fix warnings in native modules 2021-08-06 22:37:00 +02:00
Alexander Udalov
45ffe58b9c Fix warnings in idea-frontend-fir 2021-08-06 22:37:00 +02:00
Alexander Udalov
069e040af9 Fix warnings in kotlin-klib-commonizer 2021-08-06 22:37:00 +02:00
Alexander Udalov
11902c7f8f Fix warnings in daemon-related modules 2021-08-06 22:36:59 +02:00
Alexander Udalov
ca7334acb9 Fix some warnings in Gradle plugin and related modules 2021-08-06 22:36:58 +02:00
Alexander Udalov
376b420d1a Fix warnings in JS/WASM modules 2021-08-06 22:36:22 +02:00
Alexander Udalov
e0643a4185 Build: use -Xskip-runtime-version-check globally in project 2021-08-06 22:36:22 +02:00
Alexander Udalov
1599a049aa Fix warnings in scripting modules 2021-08-06 22:36:22 +02:00
Dmitriy Novozhilov
b9dd73220c [FIR] Update testdata after rebase 2021-08-06 22:57:19 +03:00
Dmitriy Novozhilov
1d491fdce6 [FIR] Don't create union call node for lambda from one when branch and call from condition of another 2021-08-06 22:57:18 +03:00
Tianyu Geng
684ef871ee FIR: unify common special names scattered around the code base 2021-08-06 22:57:17 +03:00
Tianyu Geng
263b876e6e FIR: extends scope of SENSELESS_COMPARISON
FE1.0 only reports SENSELESS_COMPARISON if one of the operand is `null`.
This change makes FIR reports also in case one of the operand has type
`Nothing?`.

In addition, fix handling of type alias in ConeTypeContext#isNullableType
2021-08-06 22:57:17 +03:00
Tianyu Geng
c7272f6986 FIR checker: SENSELESS_(COMPARISON|NULL_IN_WHEN)
Currently DFA does not set "definitely equal to null" for access to variables that got assigned `null`. For example, FIR should mark the following line as SENSELESS_COMPARISON due to `s = null` above.
 d1531f9cdd/compiler/testData/diagnostics/tests/smartCasts/alwaysNull.fir.kt (L6)

The problem is at 7e9f27436a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt (L1104)

For null assignment, ideally the type should be `Nothing?`. This is
addressed in a followup commit instead.
2021-08-06 22:57:16 +03:00
Tianyu Geng
4726dcce40 FIR DFA: smartcast variable to Nothing? on null assignment
In order to make resolution still work for members not available from
`Nothing`, we track the type without `Nothing?` and use that for
resolution instead.
2021-08-06 22:57:15 +03:00
Tianyu Geng
7e2f15f532 FIR DFA: fix logic clear aliasing
The logic should clear back aliases as well. To ensure all back aliases
don't lose any information, statements on the original variable are
copied over to its aliases.
2021-08-06 22:57:15 +03:00
Tianyu Geng
e495c722c7 FIR DFA: fix handling of equality operation 2021-08-06 22:57:14 +03:00
Tianyu Geng
0026560bd7 FIR: substitute the whole lambda body after builder inference 2021-08-06 22:57:13 +03:00
Tianyu Geng
f737d8002e FIR: allow no else branch for when on Nothing(?) 2021-08-06 22:57:12 +03:00
Tianyu Geng
e242ad955b FIR: tolerate comparison of an intersection of incompatible types
Previously, if user compares an `it<String, Int>` with `String`, the
checker reports it since the flattened types `[String, Int, Int]` are
incompatible. But technically, before flattening, the intersection type
actually contain the other side, so they should really be compatible.
2021-08-06 22:57:11 +03:00
Yahor Berdnikau
b5ea811b9f Migrated BuildCacheIT tests to new DSL.
^KT-45745 In Progress
2021-08-06 20:09:05 +02:00
Yahor Berdnikau
20afb268d1 Allow providing specific kapt options.
^KT-45745 In Progress
2021-08-06 20:09:04 +02:00
Yahor Berdnikau
3d4186bdb1 Allow enabling build cache debug information.
^KT-45745 In Progress
2021-08-06 20:09:04 +02:00
Yahor Berdnikau
e949a0d38d Add assertion checking if task was put into build cache.
^KT-45745 In Progress
2021-08-06 20:09:00 +02:00
Roman Artemev
2574c00dd9 Add index() to LocalSignature for more clear access 2021-08-06 20:49:20 +03:00
Roman Artemev
5a7298808e [JVM KLIB] Fix Type Parameter resolve 2021-08-06 20:49:19 +03:00
Roman Artemev
3dcee8fda8 [KLIB] Optimize deserialization a bit 2021-08-06 20:49:19 +03:00
Roman Artemev
7add820f0d [JS IC] Simplify code a bit 2021-08-06 20:49:17 +03:00
Roman Artemev
398b545801 [JS IC] Rollback hack 2021-08-06 20:49:17 +03:00
Roman Artemev
67f814c99f [JS IC] Don't serialize IrTypeAbbreviation in IC cache 2021-08-06 20:49:15 +03:00
Roman Artemev
d174e8c3d2 small optimization 2021-08-06 20:49:14 +03:00
Roman Artemev
9bfe502afd [JS IC] Fix signature finding in some cases
Found in KFSAD
2021-08-06 20:49:13 +03:00
Roman Artemev
15648da2b4 [PIR] Use simple fast hashCode 2021-08-06 20:49:12 +03:00
Roman Artemev
11f70412e7 [KLIB] Don't resolve delegated symbol where it could be existed 2021-08-06 20:49:12 +03:00
Roman Artemev
297e0a9f43 [JS IC] Improve IC deserializer code a bit 2021-08-06 20:49:11 +03:00
Roman Artemev
6ca87dc43f [KLIB] Drop useless set 2021-08-06 20:49:10 +03:00
Roman Artemev
aeea7147fe [JS IC] Simplify code a bit more 2021-08-06 20:49:09 +03:00
Roman Artemev
28cf9898ef [KLIB] Simplify file symbol resolve 2021-08-06 20:49:08 +03:00
Roman Artemev
6cd0d81561 [JS IC] Drop redundant enqueue 2021-08-06 20:49:07 +03:00
Roman Artemev
b1eeb1fb27 [JS IC] Don't persist temporary copies of inline functions
- drop special `IrValueParameterPublicSymbol`
 - drop special `IrAnonymousInitializerPublicSymbolImpl`
 - drop hacky `useGlobalSignatures`
2021-08-06 20:49:06 +03:00
Roman Artemev
b1251c1716 [JS IC] Drop special IdSignatureSerializer for IC 2021-08-06 20:49:04 +03:00
Roman Artemev
4a601ebf95 [JS IC] Eradicate GlobalScopeLocalDeclaration from code
- Normalize proto names
2021-08-06 20:49:03 +03:00
Roman Artemev
74d8e16d09 [JS IC] Eradicate GlobalFileLocalSignature from code
- Reduce usage of global maps
2021-08-06 20:49:02 +03:00
Roman Artemev
a0449892b2 [JS IC] Simplify signatures, don't use GlobalScopeLocalDeclaration 2021-08-06 20:49:01 +03:00
Roman Artemev
3d3c70141c [JS IC] Properly handle type parameters of Functional interfaces
- drop redundant `IrSymbolTable` and `IrIcModuleDeserializerWithBuiltIns`
2021-08-06 20:48:59 +03:00
Roman Artemev
6aed492703 [JS IR] Set proper visibility for static stub of private members 2021-08-06 20:48:58 +03:00
Yahor Berdnikau
bcf08e3293 Set jvm target validation mode to 'error'. 2021-08-06 17:53:45 +02:00
Yahor Berdnikau
d375c52830 Remove deprecated 'kotlin.useFallbackCompilerSearch' property.
^KT-46719 Fixed
2021-08-06 15:36:46 +00:00
Igor Laevsky
331681b40b WASM: Add different debug levels to the test runner 2021-08-06 17:34:22 +03:00
Igor Laevsky
5db8ec6551 WASM: Don't use intrinsics to specify NaN's 2021-08-06 17:34:21 +03:00
Igor Laevsky
4ffed54f76 WASM: Fix JS runner for standalone compiles 2021-08-06 17:34:20 +03:00
Sergey Bogolepov
18bb287d3b [K/N] Switch from cyclone to apple-a7 for Apple AArch64
This change shouldn't affect behaviour, but rather makes bitcode a bit
more consistent with what Xcode generates.
2021-08-06 14:19:42 +00:00
Sergey Bogolepov
d64cb24643 [K/N] Don't pass -target-cpu to clang
It is not supported by bitcode embedding on Apple platforms.
Instead, we set it in function attributes directly as Clang does.
2021-08-06 14:19:41 +00:00
Dmitriy Novozhilov
3a210f6c81 [Test] Temporary mute some tests because of problems with RepeatedAnnotationLowering
^KT-48131
2021-08-06 16:40:16 +03:00
Dmitriy Novozhilov
cbef031780 Advance bootstrap to 1.6.0-dev-2458 2021-08-06 16:40:07 +03:00
1683 changed files with 30123 additions and 26766 deletions

1
.bunch
View File

@@ -1,2 +1 @@
203
202

3
.gitignore vendored
View File

@@ -12,7 +12,7 @@
/android-studio/sdk
out/
/tmp
kotlin-ide/
/intellij
workspace.xml
*.versionsBackup
/idea/testData/debugger/tinyApp/classes*
@@ -68,3 +68,4 @@ distTmp/
outTmp/
/test.output
/kotlin-native/dist
kotlin-ide/

View File

@@ -25,6 +25,7 @@ import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.build.GeneratedJvmClass
import org.jetbrains.kotlin.incremental.storage.*
import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
@@ -113,7 +114,7 @@ open class IncrementalJvmCache(
}
open fun saveFileToCache(generatedClass: GeneratedJvmClass, changesCollector: ChangesCollector) {
saveClassToCache(KotlinClassInfo(generatedClass.outputClass), generatedClass.sourceFiles, changesCollector)
saveClassToCache(KotlinClassInfo.createFrom(generatedClass.outputClass), generatedClass.sourceFiles, changesCollector)
}
/**
@@ -612,16 +613,6 @@ class KotlinClassInfo private constructor(
val inlineFunctionsMap: LinkedHashMap<String, Long>
) {
constructor(kotlinClass: LocalFileKotlinClass) : this(
kotlinClass.classId,
kotlinClass.classHeader.kind,
kotlinClass.classHeader.data,
kotlinClass.classHeader.strings,
kotlinClass.classHeader.multifileClassName,
getConstantsMap(kotlinClass.fileContents),
getInlineFunctionsMap(kotlinClass.classHeader, kotlinClass.fileContents)
)
val className: JvmClassName by lazy { JvmClassName.byClassId(classId) }
fun scopeFqName(companion: Boolean = false) = when (classKind) {
@@ -630,6 +621,36 @@ class KotlinClassInfo private constructor(
}
else -> className.packageFqName
}
companion object {
fun createFrom(kotlinClass: LocalFileKotlinClass): KotlinClassInfo {
return KotlinClassInfo(
kotlinClass.classId,
kotlinClass.classHeader.kind,
kotlinClass.classHeader.data,
kotlinClass.classHeader.strings,
kotlinClass.classHeader.multifileClassName,
getConstantsMap(kotlinClass.fileContents),
getInlineFunctionsMap(kotlinClass.classHeader, kotlinClass.fileContents)
)
}
/** Creates [KotlinClassInfo] from the given classContents, or returns `null` if the class is not a kotlinc-generated class. */
fun tryCreateFrom(classContents: ByteArray): KotlinClassInfo? {
return FileBasedKotlinClass.create(classContents) { classId, _, classHeader, _ ->
KotlinClassInfo(
classId,
classHeader.kind,
classHeader.data,
classHeader.strings,
classHeader.multifileClassName,
getConstantsMap(classContents),
getInlineFunctionsMap(classHeader, classContents)
)
}
}
}
}
private fun getConstantsMap(bytes: ByteArray): LinkedHashMap<String, Any> {
@@ -694,4 +715,4 @@ private fun getInlineFunctionsMap(header: KotlinClassHeader, bytes: ByteArray):
}, 0)
return result
}
}

View File

@@ -148,7 +148,7 @@ extra["versions.kotlinx-collections-immutable-jvm"] = immutablesVersion
extra["versions.ktor-network"] = "1.0.1"
if (!project.hasProperty("versions.kotlin-native")) {
extra["versions.kotlin-native"] = "1.6.0-dev-1728"
extra["versions.kotlin-native"] = "1.6.0-dev-2972"
}
val useJvmFir by extra(project.kotlinBuildProperties.useFir)
@@ -315,15 +315,7 @@ extra["compilerArtifactsForIde"] = listOf(
// TODO: fix remaining warnings and remove this property.
extra["tasksWithWarnings"] = listOf(
":kotlin-stdlib:compileTestKotlin",
":kotlin-stdlib-jdk7:compileTestKotlin",
":kotlin-stdlib-jdk8:compileTestKotlin",
":plugins:uast-kotlin-base:compileKotlin",
":plugins:uast-kotlin-base:compileTestKotlin",
":plugins:uast-kotlin:compileKotlin",
":plugins:uast-kotlin:compileTestKotlin",
":plugins:uast-kotlin-fir:compileKotlin",
":plugins:uast-kotlin-fir:compileTestKotlin"
":kotlin-gradle-plugin:compileKotlin"
)
val tasksWithWarnings: List<String> by extra
@@ -443,6 +435,12 @@ allprojects {
project.configureShadowJarSubstitutionInCompileClasspath()
}
tasks.withType<JavaCompile> {
options.compilerArgs.add("-Xlint:deprecation")
options.compilerArgs.add("-Xlint:unchecked")
options.compilerArgs.add("-Werror")
}
val commonCompilerArgs = listOfNotNull(
"-Xopt-in=kotlin.RequiresOptIn",
"-progressive".takeIf { hasProperty("test.progressive.mode") }
@@ -460,6 +458,7 @@ allprojects {
"-Xjvm-default=compatibility",
"-Xno-optimized-callable-references",
"-Xno-kotlin-nothing-value-exception",
"-Xskip-runtime-version-check",
"-Xsuppress-deprecated-jvm-target-warning" // Remove as soon as there are no modules for JDK 1.6 & 1.7
)
@@ -475,15 +474,10 @@ allprojects {
}
if (!kotlinBuildProperties.disableWerror) {
// For compiler and stdlib, allWarningsAsErrors is configured in the corresponding "root" projects
// (compiler/build.gradle.kts and libraries/commonConfiguration.gradle).
val projectsWithWarningsAsErrors = listOf("core", "plugins").map { File(it).absoluteFile }
if (projectsWithWarningsAsErrors.any(projectDir::startsWith)) {
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
if (path !in tasksWithWarnings) {
kotlinOptions {
allWarningsAsErrors = true
}
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
if (path !in tasksWithWarnings) {
kotlinOptions {
allWarningsAsErrors = true
}
}
}

View File

@@ -79,7 +79,6 @@ val jpsStandalone by configurations.creating
val jpsStandaloneForIde by configurations.creating
val intellijCore by configurations.creating
val intellijCoreForIde by configurations.creating
val nodeJSPlugin by configurations.creating
/**
* Special repository for annotations.jar required for idea runtime only.

View File

@@ -89,4 +89,4 @@ val Project.isIdeaActive
get() = providers.systemProperty("idea.active").forUseAtConfigurationTime().isPresent
val Project.intellijCommunityDir: File
get() = rootDir.resolve("kotlin-ide/intellij/community").takeIf { it.isDirectory } ?: rootDir.resolve("kotlin-ide/intellij")
get() = rootDir.resolve("intellij/community").takeIf { it.isDirectory } ?: rootDir.resolve("intellij")

View File

@@ -41,7 +41,6 @@ tasks.withType<KotlinCompile> {
kotlinOptions.apiVersion = "1.4"
kotlinOptions.freeCompilerArgs += listOf(
"-Xskip-prerelease-check",
"-Xskip-runtime-version-check",
"-Xsuppress-version-warnings",
"-Xuse-ir" // Needed as long as languageVersion is less than 1.5.
)

View File

@@ -82,8 +82,6 @@ fun Project.intellijCoreDep() = "kotlin.build:intellij-core:${rootProject.extra[
fun Project.jpsStandalone() = "kotlin.build:jps-standalone:${rootProject.extra["versions.intellijSdk"]}"
fun Project.nodeJSPlugin() = "kotlin.build:NodeJS:${rootProject.extra["versions.idea.NodeJS"]}"
fun Project.jpsBuildTest() = "com.jetbrains.intellij.idea:jps-build-test:${rootProject.extra["versions.intellijSdk"]}"
fun Project.kotlinxCollectionsImmutable() = "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm:${rootProject.extra["versions.kotlinx-collections-immutable"]}"

View File

@@ -5,21 +5,15 @@
package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.isTopLevelInPackage
import org.jetbrains.kotlin.name.Name
val COROUTINE_SUSPENDED_NAME = Name.identifier("COROUTINE_SUSPENDED")
fun FunctionDescriptor.isBuiltInIntercepted(languageVersionSettings: LanguageVersionSettings): Boolean =
!languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines) &&
isTopLevelInPackage("intercepted", languageVersionSettings.coroutinesIntrinsicsPackageFqName().asString())
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings: LanguageVersionSettings): Boolean =
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(): Boolean =
isTopLevelInPackage(
"suspendCoroutineUninterceptedOrReturn",
languageVersionSettings.coroutinesIntrinsicsPackageFqName().asString()
StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.asString()
)

View File

@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
@@ -26,7 +26,7 @@ class AccessorForConstructorDescriptor(
containingDeclaration: DeclarationDescriptor,
override val superCallTarget: ClassDescriptor?,
override val accessorKind: AccessorKind
) : AbstractAccessorForFunctionDescriptor(containingDeclaration, Name.special("<init>")),
) : AbstractAccessorForFunctionDescriptor(containingDeclaration, SpecialNames.INIT),
ClassConstructorDescriptor,
AccessorForCallableDescriptor<ConstructorDescriptor> {

View File

@@ -475,7 +475,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
List<Type> superCtorArgTypes = new ArrayList<>();
if (superClassAsmType.equals(LAMBDA) || functionReferenceTarget != null ||
CoroutineCodegenUtilKt.isCoroutineSuperClass(state.getLanguageVersionSettings(), superClassAsmType.getInternalName())
CoroutineCodegenUtilKt.isCoroutineSuperClass(superClassAsmType.getInternalName())
) {
iv.iconst(CodegenUtilKt.getArity(funDescriptor));
superCtorArgTypes.add(Type.INT_TYPE);

View File

@@ -89,7 +89,6 @@ import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.checker.ClassicTypeSystemContextImpl;
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS;
import org.jetbrains.kotlin.types.model.KotlinTypeMarker;
import org.jetbrains.kotlin.types.model.TypeParameterMarker;
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
import org.jetbrains.kotlin.util.OperatorNameConventions;
@@ -1288,11 +1287,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull
private static CallableDescriptor unwrapOriginalReceiverOwnerForSuspendLambda(@NotNull MethodContext context) {
FunctionDescriptor originalForDoResume =
context.getFunctionDescriptor().getUserData(CoroutineCodegenUtilKt.INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME);
FunctionDescriptor originalForInvokeSuspend =
context.getFunctionDescriptor().getUserData(CoroutineCodegenUtilKt.INITIAL_SUSPEND_DESCRIPTOR_FOR_INVOKE_SUSPEND);
if (originalForDoResume != null) {
return originalForDoResume;
if (originalForInvokeSuspend != null) {
return originalForInvokeSuspend;
}
if (context.getFunctionDescriptor().isSuspend()) {
@@ -2617,26 +2616,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
? coroutineInstanceValueForSuspensionPoint
: getContinuationParameterFromEnclosingSuspendFunction(resolvedCall);
if (coroutineInstanceValue != null && needsExperimentalCoroutinesWrapper(resolvedCall.getCandidateDescriptor())) {
StackValue releaseContinuation = coroutineInstanceValue;
coroutineInstanceValue = new StackValue(CoroutineCodegenUtilKt.EXPERIMENTAL_CONTINUATION_ASM_TYPE) {
@Override
public void putSelector(
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v
) {
releaseContinuation.put(CoroutineCodegenUtilKt.RELEASE_CONTINUATION_ASM_TYPE, v);
invokeCoroutineMigrationMethod(
v,
"toExperimentalContinuation",
Type.getMethodDescriptor(
CoroutineCodegenUtilKt.EXPERIMENTAL_CONTINUATION_ASM_TYPE,
CoroutineCodegenUtilKt.RELEASE_CONTINUATION_ASM_TYPE
)
);
}
};
}
tempVariables.put(continuationExpression, coroutineInstanceValue);
}
@@ -2774,7 +2753,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
SuspensionPointKind suspensionPointKind =
CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, this, state.getLanguageVersionSettings());
CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, this);
boolean maybeSuspensionPoint = suspensionPointKind != SuspensionPointKind.NEVER && !insideCallableReference();
boolean isConstructor = resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor;
if (!(callableMethod instanceof IntrinsicWithSpecialReceiver)) {
@@ -2833,7 +2812,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
KotlinType unboxedInlineClass = CoroutineCodegenUtilKt.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(
(FunctionDescriptor) resolvedCall.getResultingDescriptor(), typeMapper);
if (unboxedInlineClass != null) {
CoroutineCodegenUtilKt.generateCoroutineSuspendedCheck(v, state.getLanguageVersionSettings());
CoroutineCodegenUtilKt.generateCoroutineSuspendedCheck(v);
}
}
@@ -2948,7 +2927,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor original =
CoroutineCodegenUtilKt.getOriginalSuspendFunctionView(
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal())),
bindingContext, state
bindingContext
);
FunctionDescriptor functionDescriptor =
@@ -5243,7 +5222,7 @@ The "returned" value of try expression with no finally is either the last expres
}
CodegenUtilKt.generateAsCast(
v, rightKotlinType, boxedRightType, safeAs, state.getLanguageVersionSettings(), state.getUnifiedNullChecks()
v, rightKotlinType, boxedRightType, safeAs, state.getUnifiedNullChecks()
);
return Unit.INSTANCE;
@@ -5297,7 +5276,7 @@ The "returned" value of try expression with no finally is either the last expres
return null;
}
CodegenUtilKt.generateIsCheck(v, rhsKotlinType, type, state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines));
CodegenUtilKt.generateIsCheck(v, rhsKotlinType, type);
return null;
});
}

View File

@@ -481,8 +481,7 @@ public class FunctionCodegen {
}
if (!functionDescriptor.isExternal()) {
generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen, state.getJvmDefaultMode(),
state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines));
generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen, state.getJvmDefaultMode());
}
else if (staticInCompanionObject) {
// native @JvmStatic foo() in companion object should delegate to the static native function moved to the outer class
@@ -583,8 +582,7 @@ public class FunctionCodegen {
@NotNull JvmMethodSignature signature,
@NotNull FunctionGenerationStrategy strategy,
@NotNull MemberCodegen<?> parentCodegen,
@NotNull JvmDefaultMode jvmDefaultMode,
boolean isReleaseCoroutines
@NotNull JvmDefaultMode jvmDefaultMode
) {
mv.visitCode();
@@ -594,8 +592,7 @@ public class FunctionCodegen {
KotlinTypeMapper typeMapper = parentCodegen.typeMapper;
if (BuiltinSpecialBridgesUtil.shouldHaveTypeSafeBarrier(functionDescriptor, typeMapper::mapAsmMethod)) {
generateTypeCheckBarrierIfNeeded(
new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), null, typeMapper,
isReleaseCoroutines);
new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), null, typeMapper);
}
Label methodEntry = null;
@@ -1430,8 +1427,7 @@ public class FunctionCodegen {
MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv);
if (delegateTo.getArgumentTypes().length > 0 && isSpecialBridge) {
generateTypeCheckBarrierIfNeeded(iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes(), typeMapper,
state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines));
generateTypeCheckBarrierIfNeeded(iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes(), typeMapper);
}
iv.load(0, OBJECT_TYPE);
@@ -1477,8 +1473,7 @@ public class FunctionCodegen {
@NotNull FunctionDescriptor descriptor,
@NotNull Type returnType,
@Nullable Type[] delegateParameterTypes,
@NotNull KotlinTypeMapper typeMapper,
boolean isReleaseCoroutines
@NotNull KotlinTypeMapper typeMapper
) {
BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription typeSafeBarrierDescription =
BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor);
@@ -1512,7 +1507,7 @@ public class FunctionCodegen {
} else {
targetBoxedType = boxType(delegateParameterTypes[i]);
}
CodegenUtilKt.generateIsCheck(iv, kotlinType, targetBoxedType, isReleaseCoroutines);
CodegenUtilKt.generateIsCheck(iv, kotlinType, targetBoxedType);
iv.ifeq(defaultBranch);
}
}

View File

@@ -5,13 +5,12 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.codegen.coroutines.coroutinesJvmInternalPackageFqName
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
import org.jetbrains.kotlin.codegen.coroutines.isSuspendLambdaOrLocalFunction
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
@@ -33,8 +32,7 @@ class JvmRuntimeTypes(
private val generateOptimizedCallableReferenceSuperClasses: Boolean
) {
private val kotlinJvmInternalPackage = MutablePackageFragmentDescriptor(module, FqName("kotlin.jvm.internal"))
private val kotlinCoroutinesJvmInternalPackage =
MutablePackageFragmentDescriptor(module, languageVersionSettings.coroutinesJvmInternalPackageFqName())
private val kotlinCoroutinesJvmInternalPackage = MutablePackageFragmentDescriptor(module, COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME)
private fun internal(className: String, packageFragment: PackageFragmentDescriptor = kotlinJvmInternalPackage): Lazy<ClassDescriptor> =
lazy { createClass(packageFragment, className) }
@@ -53,24 +51,16 @@ class JvmRuntimeTypes(
private val localVariableReference: ClassDescriptor by internal("LocalVariableReference")
private val mutableLocalVariableReference: ClassDescriptor by internal("MutableLocalVariableReference")
private val coroutineImpl: ClassDescriptor by internal("CoroutineImpl", kotlinCoroutinesJvmInternalPackage)
private val continuationImpl: ClassDescriptor by coroutinesInternal("ContinuationImpl")
private val restrictedContinuationImpl: ClassDescriptor by coroutinesInternal("RestrictedContinuationImpl")
private val suspendLambda: ClassDescriptor by coroutinesInternal("SuspendLambda")
private val restrictedSuspendLambda: ClassDescriptor by coroutinesInternal("RestrictedSuspendLambda")
private val suspendFunctionInterface: ClassDescriptor? by lazy {
if (languageVersionSettings.isReleaseCoroutines())
createClass(kotlinCoroutinesJvmInternalPackage, "SuspendFunction", ClassKind.INTERFACE)
else null
createClass(kotlinCoroutinesJvmInternalPackage, "SuspendFunction", ClassKind.INTERFACE)
}
private fun createCoroutineSuperClass(className: String): ClassDescriptor {
return if (languageVersionSettings.isReleaseCoroutines())
createClass(kotlinCoroutinesJvmInternalPackage, className)
else
coroutineImpl
}
private fun createCoroutineSuperClass(className: String): ClassDescriptor = createClass(kotlinCoroutinesJvmInternalPackage, className)
private val propertyReferences: List<ClassDescriptor> by propertyClasses("PropertyReference", "")
private val mutablePropertyReferences: List<ClassDescriptor> by propertyClasses("MutablePropertyReference", "")
@@ -94,7 +84,7 @@ class JvmRuntimeTypes(
fun getSupertypesForClosure(descriptor: FunctionDescriptor): Collection<KotlinType> {
val actualFunctionDescriptor =
if (descriptor.isSuspend)
getOrCreateJvmSuspendFunctionView(descriptor, languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))
getOrCreateJvmSuspendFunctionView(descriptor)
else
descriptor
@@ -118,7 +108,7 @@ class JvmRuntimeTypes(
if (descriptor.isSuspend) {
return mutableListOf<KotlinType>().apply {
if (actualFunctionDescriptor.extensionReceiverParameter?.type
?.isRestrictsSuspensionReceiver(languageVersionSettings) == true
?.isRestrictsSuspensionReceiver() == true
) {
if (descriptor.isSuspendLambdaOrLocalFunction()) {
add(restrictedSuspendLambda.defaultType)

View File

@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.sam.JavaSingleAbstractMethodUtils;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.name.SpecialNames;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.stubs.KotlinFileStub;
import org.jetbrains.kotlin.resolve.BindingContext;
@@ -298,7 +299,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
private String getName(ClassDescriptor classDescriptor) {
String base = peekFromStack(nameStack);
Name descriptorName = safeIdentifier(classDescriptor.getName());
Name descriptorName = SpecialNames.safeIdentifier(classDescriptor.getName());
if (DescriptorUtils.isTopLevelDeclaration(classDescriptor)) {
return base.isEmpty() ? descriptorName.asString() : base + '/' + descriptorName;
}
@@ -476,7 +477,6 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
SimpleFunctionDescriptor jvmSuspendFunctionView =
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
functionDescriptor,
languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines),
this.bindingContext
);
@@ -713,54 +713,6 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
super.visitCallExpression(expression);
checkSamCall(expression);
checkCrossinlineCall(expression);
recordSuspendFunctionTypeWrapperForArguments(expression);
}
private void recordSuspendFunctionTypeWrapperForArguments(@NotNull KtCallExpression expression) {
ResolvedCall<?> call = CallUtilKt.getResolvedCall(expression, bindingContext);
if (call == null) return;
CallableDescriptor descriptor = call.getResultingDescriptor();
if (!CodegenUtilKt.needsExperimentalCoroutinesWrapper(descriptor)) return;
List<ResolvedValueArgument> argumentsByIndex = call.getValueArgumentsByIndex();
if (argumentsByIndex == null) return;
for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) {
ResolvedValueArgument resolvedValueArgument = argumentsByIndex.get(parameter.getIndex());
if (!(resolvedValueArgument instanceof ExpressionValueArgument)) continue;
ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument();
if (valueArgument == null) continue;
KtExpression argumentExpression = valueArgument.getArgumentExpression();
if (argumentExpression == null) continue;
recordSuspendFunctionTypeWrapperForArgument(parameter, argumentExpression);
}
ReceiverValue receiver = call.getExtensionReceiver();
if (descriptor.getExtensionReceiverParameter() != null && receiver instanceof ExpressionReceiver) {
recordSuspendFunctionTypeWrapperForArgument(
descriptor.getExtensionReceiverParameter(),
((ExpressionReceiver) receiver).getExpression()
);
}
}
private void recordSuspendFunctionTypeWrapperForArgument(ParameterDescriptor parameter, KtExpression argumentExpression) {
if (FunctionTypesKt.isSuspendFunctionTypeOrSubtype(parameter.getType())) {
// SuspendFunctionN type is mapped to is mapped to FunctionTypeN+1, but we also need to remove an argument for return type
// So, it could be parameter.getType().getArguments().size() + 1 - 1
int functionTypeArity = parameter.getType().getArguments().size();
Type functionType = Type.getObjectType(NUMBERED_FUNCTION_PREFIX + functionTypeArity);
bindingTrace.record(
FUNCTION_TYPE_FOR_SUSPEND_WRAPPER,
argumentExpression,
functionType
);
}
}
private void checkCrossinlineCall(@NotNull KtCallExpression expression) {

View File

@@ -13,15 +13,13 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.context.CodegenContext
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
import org.jetbrains.kotlin.codegen.context.MultifileClassFacadeContext
import org.jetbrains.kotlin.codegen.coroutines.continuationAsmType
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_ASM_TYPE
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
import org.jetbrains.kotlin.codegen.inline.NUMBERED_FUNCTION_PREFIX
import org.jetbrains.kotlin.codegen.inline.ReificationArgument
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
@@ -45,8 +43,6 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor.CoroutinesCompatibilityMode
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
@@ -70,8 +66,7 @@ internal val JAVA_LANG_DEPRECATED = Type.getType(Deprecated::class.java).descrip
fun generateIsCheck(
v: InstructionAdapter,
kotlinType: KotlinType,
asmType: Type,
isReleaseCoroutines: Boolean
asmType: Type
) {
if (TypeUtils.isNullableType(kotlinType)) {
val nope = Label()
@@ -82,7 +77,7 @@ fun generateIsCheck(
ifnull(nope)
TypeIntrinsics.instanceOf(this, kotlinType, asmType, isReleaseCoroutines)
TypeIntrinsics.instanceOf(this, kotlinType, asmType)
goTo(end)
@@ -93,7 +88,7 @@ fun generateIsCheck(
mark(end)
}
} else {
TypeIntrinsics.instanceOf(v, kotlinType, asmType, isReleaseCoroutines)
TypeIntrinsics.instanceOf(v, kotlinType, asmType)
}
}
@@ -102,7 +97,6 @@ fun generateAsCast(
kotlinType: KotlinType,
asmType: Type,
isSafe: Boolean,
languageVersionSettings: LanguageVersionSettings,
unifiedNullChecks: Boolean,
) {
if (!isSafe) {
@@ -112,7 +106,7 @@ fun generateAsCast(
} else {
with(v) {
dup()
TypeIntrinsics.instanceOf(v, kotlinType, asmType, languageVersionSettings.isReleaseCoroutines())
TypeIntrinsics.instanceOf(v, kotlinType, asmType)
val ok = Label()
ifne(ok)
pop()
@@ -444,14 +438,10 @@ fun KotlinType.isInlineClassTypeWithPrimitiveEquality(): Boolean {
return false
}
fun CallableDescriptor.needsExperimentalCoroutinesWrapper() =
(this as? DeserializedMemberDescriptor)?.coroutinesExperimentalCompatibilityMode == CoroutinesCompatibilityMode.NEEDS_WRAPPER
fun recordCallLabelForLambdaArgument(declaration: KtFunctionLiteral, bindingTrace: BindingTrace) {
val labelName = getCallLabelForLambdaArgument(declaration, bindingTrace.bindingContext) ?: return
val functionDescriptor = bindingTrace[BindingContext.FUNCTION, declaration] ?: return
bindingTrace.record(CodegenBinding.CALL_LABEL_FOR_LAMBDA_ARGUMENT, functionDescriptor, labelName)
}
fun getCallLabelForLambdaArgument(declaration: KtFunctionLiteral, bindingContext: BindingContext): String? {
@@ -647,7 +637,7 @@ private fun generateLambdaForRunSuspend(
}
visitVarInsn(ALOAD, 1)
val continuationInternalName = state.languageVersionSettings.continuationAsmType().internalName
val continuationInternalName = CONTINUATION_ASM_TYPE.internalName
visitTypeInsn(
CHECKCAST,

View File

@@ -6,9 +6,9 @@
package org.jetbrains.kotlin.codegen.context
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.binding.MutableClosure
import org.jetbrains.kotlin.config.coroutinesPackageFqName
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.descriptors.isTopLevelInPackage
@@ -17,25 +17,26 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getParentResolvedCall
import org.jetbrains.kotlin.resolve.source.getPsi
class InlineLambdaContext(
functionDescriptor: FunctionDescriptor,
contextKind: OwnerKind,
parentContext: CodegenContext<*>,
closure: MutableClosure?,
val isCrossInline: Boolean,
private val isPropertyReference: Boolean
functionDescriptor: FunctionDescriptor,
contextKind: OwnerKind,
parentContext: CodegenContext<*>,
closure: MutableClosure?,
val isCrossInline: Boolean,
private val isPropertyReference: Boolean
) : MethodContext(functionDescriptor, contextKind, parentContext, closure, false) {
override fun getFirstCrossInlineOrNonInlineContext(): CodegenContext<*> {
if (isCrossInline && !isSuspendIntrinsicParameter()) return this
val parent = if (isPropertyReference) parentContext as? AnonymousClassContext else { parentContext as? ClosureContext } ?:
throw AssertionError(
"Parent of inlining lambda body should be " +
"${if (isPropertyReference) "ClosureContext" else "AnonymousClassContext"}, but: $parentContext"
)
val parent = if (isPropertyReference) parentContext as? AnonymousClassContext else {
parentContext as? ClosureContext
} ?: throw AssertionError(
"Parent of inlining lambda body should be " +
"${if (isPropertyReference) "ClosureContext" else "AnonymousClassContext"}, but: $parentContext"
)
val grandParent = parent.parentContext ?:
throw AssertionError("Parent context of lambda class context should exist: $contextDescriptor")
val grandParent =
parent.parentContext ?: throw AssertionError("Parent context of lambda class context should exist: $contextDescriptor")
return grandParent.firstCrossInlineOrNonInlineContext
}
@@ -44,7 +45,7 @@ class InlineLambdaContext(
if (contextDescriptor !is AnonymousFunctionDescriptor) return false
val resolvedCall = (contextDescriptor.source.getPsi() as? KtElement).getParentResolvedCall(state.bindingContext) ?: return false
val descriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return false
return descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(state.languageVersionSettings)
|| descriptor.isTopLevelInPackage("suspendCoroutine", state.languageVersionSettings.coroutinesPackageFqName().asString())
return descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn()
|| descriptor.isTopLevelInPackage("suspendCoroutine", StandardNames.COROUTINES_PACKAGE_FQ_NAME.asString())
}
}

View File

@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.optimization.boxing.isPrimitiveBoxing
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
@@ -15,10 +16,9 @@ import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.*
private val BOXING_CLASS_INTERNAL_NAME =
RELEASE_COROUTINES_VERSION_SETTINGS.coroutinesJvmInternalPackageFqName().child(Name.identifier("Boxing")).topLevelClassInternalName()
StandardNames.COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("Boxing")).topLevelClassInternalName()
@OptIn(ExperimentalStdlibApi::class)
object ChangeBoxingMethodTransformer : MethodTransformer() {

View File

@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.codegen.coroutines
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA
@@ -17,8 +18,6 @@ import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHO
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
@@ -41,7 +40,6 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.serialization.DescriptorSerializer
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.MethodVisitor
@@ -56,7 +54,7 @@ abstract class AbstractCoroutineCodegen(
element: KtElement,
closureContext: ClosureContext,
classBuilder: ClassBuilder,
private val userDataForDoResume: Map<out CallableDescriptor.UserDataKey<*>, *>? = null
private val userDataForInvokeSuspend: Map<out CallableDescriptor.UserDataKey<*>, *>? = null
) : ClosureCodegen(
outerExpressionCodegen.state,
element, null, closureContext, null,
@@ -67,17 +65,10 @@ abstract class AbstractCoroutineCodegen(
protected val languageVersionSettings = outerExpressionCodegen.state.languageVersionSettings
protected val methodToImplement =
if (languageVersionSettings.isReleaseCoroutines())
createImplMethod(
INVOKE_SUSPEND_METHOD_NAME,
SUSPEND_CALL_RESULT_NAME to classDescriptor.module.getResult(classDescriptor.builtIns.anyType)
)
else
createImplMethod(
DO_RESUME_METHOD_NAME,
"data" to classDescriptor.builtIns.nullableAnyType,
"throwable" to classDescriptor.builtIns.throwable.defaultType.makeNullable()
)
createImplMethod(
INVOKE_SUSPEND_METHOD_NAME,
SUSPEND_CALL_RESULT_NAME to classDescriptor.module.getResult(classDescriptor.builtIns.anyType)
)
private fun createImplMethod(name: String, vararg parameters: Pair<String, KotlinType>) =
SimpleFunctionDescriptorImpl.create(
@@ -94,7 +85,7 @@ abstract class AbstractCoroutineCodegen(
builtIns.nullableAnyType,
Modality.FINAL,
DescriptorVisibilities.PUBLIC,
userDataForDoResume
userDataForInvokeSuspend
)
}
@@ -109,7 +100,7 @@ abstract class AbstractCoroutineCodegen(
override fun generateConstructor(): Method {
val args = calculateConstructorParameters(typeMapper, languageVersionSettings, closure, asmType)
val argTypes = args.map { it.fieldType }.plus(languageVersionSettings.continuationAsmType()).toTypedArray()
val argTypes = args.map { it.fieldType }.plus(CONTINUATION_ASM_TYPE).toTypedArray()
val constructor = Method("<init>", Type.VOID_TYPE, argTypes)
val mv = v.newMethod(
@@ -124,18 +115,17 @@ abstract class AbstractCoroutineCodegen(
iv.generateClosureFieldsInitializationFromParameters(closure, args)
iv.load(0, AsmTypes.OBJECT_TYPE)
val hasArityParameter = !languageVersionSettings.isReleaseCoroutines() || passArityToSuperClass
if (hasArityParameter) {
iv.iconst(if (passArityToSuperClass) funDescriptor.arity else 0)
if (passArityToSuperClass) {
iv.iconst(funDescriptor.arity)
}
iv.load(argTypes.map { it.size }.sum(), AsmTypes.OBJECT_TYPE)
val parameters =
if (hasArityParameter)
listOf(Type.INT_TYPE, languageVersionSettings.continuationAsmType())
if (passArityToSuperClass)
listOf(Type.INT_TYPE, CONTINUATION_ASM_TYPE)
else
listOf(languageVersionSettings.continuationAsmType())
listOf(CONTINUATION_ASM_TYPE)
val superClassConstructorDescriptor = Type.getMethodDescriptor(
Type.VOID_TYPE,
@@ -148,9 +138,7 @@ abstract class AbstractCoroutineCodegen(
FunctionCodegen.endVisit(iv, "constructor", element)
}
if (languageVersionSettings.isReleaseCoroutines()) {
v.newField(JvmDeclarationOrigin.NO_ORIGIN, AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "label", "I", null, null)
}
v.newField(JvmDeclarationOrigin.NO_ORIGIN, AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "label", "I", null, null)
return constructor
}
@@ -167,7 +155,7 @@ class CoroutineCodegenForLambda private constructor(
private val forInline: Boolean
) : AbstractCoroutineCodegen(
outerExpressionCodegen, element, closureContext, classBuilder,
userDataForDoResume = mapOf(INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME to originalSuspendFunctionDescriptor)
userDataForInvokeSuspend = mapOf(INITIAL_SUSPEND_DESCRIPTOR_FOR_INVOKE_SUSPEND to originalSuspendFunctionDescriptor)
) {
private val builtIns = funDescriptor.builtIns
@@ -215,8 +203,7 @@ class CoroutineCodegenForLambda private constructor(
funDescriptor.typeParameters,
funDescriptor.valueParameters,
funDescriptor.module.getContinuationOfTypeOrAny(
builtIns.unitType,
state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
builtIns.unitType
),
funDescriptor.modality,
DescriptorVisibilities.PUBLIC
@@ -231,14 +218,11 @@ class CoroutineCodegenForLambda private constructor(
"too many arguments of create to have an erased signature: $argumentsNum: $typedCreate"
}
return typedCreate.module.resolveClassByFqName(
languageVersionSettings.coroutinesJvmInternalPackageFqName().child(
if (languageVersionSettings.isReleaseCoroutines())
Name.identifier("BaseContinuationImpl")
else
Name.identifier("CoroutineImpl")
StandardNames.COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(
Name.identifier("BaseContinuationImpl")
),
NoLookupLocation.FROM_BACKEND
).sure { "BaseContinuationImpl or CoroutineImpl is not found" }.defaultType.memberScope
).sure { "BaseContinuationImpl is not found" }.defaultType.memberScope
.getContributedFunctions(typedCreate.name, NoLookupLocation.FROM_BACKEND)
.find { it.valueParameters.size == argumentsNum }
.sure { "erased parent of $typedCreate is not found" }
@@ -365,7 +349,7 @@ class CoroutineCodegenForLambda private constructor(
v.thisName,
typeMapper.mapFunctionName(createCoroutineDescriptor, null),
Type.getMethodDescriptor(
languageVersionSettings.continuationAsmType(),
CONTINUATION_ASM_TYPE,
*createArgumentTypes.toTypedArray()
),
false
@@ -373,11 +357,7 @@ class CoroutineCodegenForLambda private constructor(
checkcast(Type.getObjectType(v.thisName))
// .doResume(Unit)
if (languageVersionSettings.isReleaseCoroutines()) {
invokeInvokeSuspendWithUnit(v.thisName)
} else {
invokeDoResumeWithUnit(v.thisName)
}
invokeInvokeSuspendWithUnit(v.thisName)
areturn(AsmTypes.OBJECT_TYPE)
}
@@ -540,15 +520,14 @@ class CoroutineCodegenForLambda private constructor(
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
mv, access, name, desc, null, null,
containingClassInternalName = v.thisName,
obtainClassBuilderForCoroutineState = { v },
isForNamedFunction = false,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
disableTailCallOptimizationForFunctionReturningUnit = false,
reportSuspensionPointInsideMonitor = { reportSuspensionPointInsideMonitor(element, state, it) },
lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0,
sourceFile = element.containingKtFile.name,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = v.thisName,
isForNamedFunction = false,
languageVersionSettings = languageVersionSettings,
disableTailCallOptimizationForFunctionReturningUnit = false,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS),
initialVarsCountByType = varsCountByType
)
@@ -625,7 +604,7 @@ class CoroutineCodegenForNamedFunction private constructor(
private val labelFieldStackValue by lazy {
StackValue.field(
FieldInfo.createForHiddenField(
computeLabelOwner(languageVersionSettings, v.thisName),
Type.getObjectType(v.thisName),
Type.INT_TYPE,
COROUTINE_LABEL_FIELD_NAME
),
@@ -647,44 +626,25 @@ class CoroutineCodegenForNamedFunction private constructor(
}
override fun generateClosureBody() {
generateResumeImpl()
if (!languageVersionSettings.isReleaseCoroutines()) {
generateGetLabelMethod()
generateSetLabelMethod()
}
generateInvokeSuspend()
v.newField(
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_SYNTHETIC or AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
languageVersionSettings.dataFieldName(), AsmTypes.OBJECT_TYPE.descriptor, null, null
CONTINUATION_RESULT_FIELD_NAME, AsmTypes.OBJECT_TYPE.descriptor, null, null
)
if (!languageVersionSettings.isReleaseCoroutines()) {
v.newField(
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_SYNTHETIC or AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_TYPE.descriptor, null, null
)
}
}
private fun generateResumeImpl() {
private fun generateInvokeSuspend() {
functionCodegen.generateMethod(
OtherOrigin(element),
methodToImplement,
object : FunctionGenerationStrategy.CodegenBased(state) {
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
StackValue.field(
AsmTypes.OBJECT_TYPE, Type.getObjectType(v.thisName), languageVersionSettings.dataFieldName(), false,
AsmTypes.OBJECT_TYPE, Type.getObjectType(v.thisName), CONTINUATION_RESULT_FIELD_NAME, false,
StackValue.LOCAL_0
).store(StackValue.local(1, AsmTypes.OBJECT_TYPE), codegen.v)
if (!languageVersionSettings.isReleaseCoroutines()) {
StackValue.field(
AsmTypes.JAVA_THROWABLE_TYPE, Type.getObjectType(v.thisName), EXCEPTION_FIELD_NAME, false,
StackValue.LOCAL_0
).store(StackValue.local(2, AsmTypes.JAVA_THROWABLE_TYPE), codegen.v)
}
labelFieldStackValue.store(
StackValue.operation(Type.INT_TYPE) {
labelFieldStackValue.put(Type.INT_TYPE, it)
@@ -736,7 +696,7 @@ class CoroutineCodegenForNamedFunction private constructor(
with(codegen.v) {
// We need to box the returned inline class in resume path.
// But first, check for COROUTINE_SUSPENDED, since the function can return it
generateCoroutineSuspendedCheck(languageVersionSettings)
generateCoroutineSuspendedCheck()
// Now we box the inline class
StackValue.coerce(AsmTypes.OBJECT_TYPE, typeMapper.mapType(inlineClassToBoxInInvokeSuspend), this)
StackValue.boxInlineClass(inlineClassToBoxInInvokeSuspend, this, typeMapper)

View File

@@ -9,15 +9,10 @@ import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.optimization.common.*
import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
@@ -49,7 +44,6 @@ class CoroutineTransformerMethodVisitor(
obtainClassBuilderForCoroutineState: () -> ClassBuilder,
private val isForNamedFunction: Boolean,
private val shouldPreserveClassInitialization: Boolean,
private val languageVersionSettings: LanguageVersionSettings,
// Since tail-call optimization of functions with Unit return type relies on ability of call-site to recognize them,
// in order to ignore return value and push Unit, when we cannot ensure this ability, for example, when the function overrides function,
// returning Any, we need to disable tail-call optimization for these functions.
@@ -73,7 +67,6 @@ class CoroutineTransformerMethodVisitor(
private var continuationIndex = if (isForNamedFunction) -1 else 0
private var dataIndex = if (isForNamedFunction) -1 else 1
private var exceptionIndex = if (isForNamedFunction || languageVersionSettings.isReleaseCoroutines()) -1 else 2
override fun performTransformations(methodNode: MethodNode) {
removeFakeContinuationConstructorCall(methodNode)
@@ -89,9 +82,7 @@ class CoroutineTransformerMethodVisitor(
val suspensionPoints = collectSuspensionPoints(methodNode)
RedundantLocalsEliminationMethodTransformer(suspensionPoints)
.transform(containingClassInternalName, methodNode)
if (languageVersionSettings.isReleaseCoroutines()) {
ChangeBoxingMethodTransformer.transform(containingClassInternalName, methodNode)
}
ChangeBoxingMethodTransformer.transform(containingClassInternalName, methodNode)
updateMaxStack(methodNode)
checkForSuspensionPointInsideMonitor(methodNode, suspensionPoints)
@@ -105,7 +96,6 @@ class CoroutineTransformerMethodVisitor(
}
val examiner = MethodNodeExaminer(
languageVersionSettings,
containingClassInternalName,
methodNode,
suspensionPoints,
@@ -119,9 +109,6 @@ class CoroutineTransformerMethodVisitor(
}
dataIndex = methodNode.maxLocals++
if (!languageVersionSettings.isReleaseCoroutines()) {
exceptionIndex = methodNode.maxLocals++
}
continuationIndex = methodNode.maxLocals++
prepareMethodNodePreludeForNamedFunction(methodNode)
@@ -158,7 +145,7 @@ class CoroutineTransformerMethodVisitor(
insertBefore(
actualCoroutineStart,
insnListOf(
*withInstructionAdapter { loadCoroutineSuspendedMarker(languageVersionSettings) }.toArray(),
*withInstructionAdapter { loadCoroutineSuspendedMarker() }.toArray(),
tableSwitchLabel,
// Allow debugger to stop on enter into suspend function
LineNumberNode(lineNumber, tableSwitchLabel),
@@ -176,7 +163,7 @@ class CoroutineTransformerMethodVisitor(
)
insert(firstStateLabel, withInstructionAdapter {
generateResumeWithExceptionCheck(languageVersionSettings.isReleaseCoroutines(), dataIndex, exceptionIndex)
generateResumeWithExceptionCheck(dataIndex)
})
insert(last, defaultLabel)
@@ -192,11 +179,9 @@ class CoroutineTransformerMethodVisitor(
dropUnboxInlineClassMarkers(methodNode, suspensionPoints)
methodNode.removeEmptyCatchBlocks()
updateLvtAccordingToLiveness(methodNode, isForNamedFunction)
updateLvtAccordingToLiveness(methodNode, isForNamedFunction, stateLabels)
if (languageVersionSettings.isReleaseCoroutines()) {
writeDebugMetadata(methodNode, suspensionPointLineNumbers, spilledToVariableMapping)
}
writeDebugMetadata(methodNode, suspensionPointLineNumbers, spilledToVariableMapping)
}
// When suspension point is inlined, it is in range of fake inliner variables.
@@ -263,7 +248,7 @@ class CoroutineTransformerMethodVisitor(
methodNode.localVariables.add(
LocalVariableNode(
SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME,
languageVersionSettings.continuationAsmType().descriptor,
CONTINUATION_ASM_TYPE.descriptor,
null,
startLabel,
endLabel,
@@ -402,7 +387,7 @@ class CoroutineTransformerMethodVisitor(
methodNode.instructions.add(withInstructionAdapter { mark(endLabel) })
methodNode.visitLocalVariable(
CONTINUATION_VARIABLE_NAME,
languageVersionSettings.continuationAsmType().descriptor,
CONTINUATION_ASM_TYPE.descriptor,
null,
startLabel,
endLabel,
@@ -430,33 +415,17 @@ class CoroutineTransformerMethodVisitor(
}
private fun InstructionAdapter.getLabel() {
if (isForNamedFunction && !languageVersionSettings.isReleaseCoroutines())
invokevirtual(
classBuilderForCoroutineState.thisName,
"getLabel",
Type.getMethodDescriptor(Type.INT_TYPE),
false
)
else
getfield(
computeLabelOwner(languageVersionSettings, classBuilderForCoroutineState.thisName).internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
)
getfield(
Type.getObjectType(classBuilderForCoroutineState.thisName).internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
)
}
private fun InstructionAdapter.setLabel() {
if (isForNamedFunction && !languageVersionSettings.isReleaseCoroutines())
invokevirtual(
classBuilderForCoroutineState.thisName,
"setLabel",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE),
false
)
else
putfield(
computeLabelOwner(languageVersionSettings, classBuilderForCoroutineState.thisName).internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
)
putfield(
Type.getObjectType(classBuilderForCoroutineState.thisName).internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
)
}
private fun updateMaxStack(methodNode: MethodNode) {
@@ -534,8 +503,7 @@ class CoroutineTransformerMethodVisitor(
needDispatchReceiver,
internalNameForDispatchReceiver,
containingClassInternalName,
classBuilderForCoroutineState,
languageVersionSettings
classBuilderForCoroutineState
)
visitVarInsn(Opcodes.ASTORE, continuationIndex)
@@ -543,19 +511,13 @@ class CoroutineTransformerMethodVisitor(
visitLabel(afterCoroutineStateCreated)
visitVarInsn(Opcodes.ALOAD, continuationIndex)
getfield(classBuilderForCoroutineState.thisName, languageVersionSettings.dataFieldName(), AsmTypes.OBJECT_TYPE.descriptor)
getfield(classBuilderForCoroutineState.thisName, CONTINUATION_RESULT_FIELD_NAME, AsmTypes.OBJECT_TYPE.descriptor)
visitVarInsn(Opcodes.ASTORE, dataIndex)
val resultStartLabel = Label()
visitLabel(resultStartLabel)
addContinuationAndResultToLvt(methodNode, afterCoroutineStateCreated, resultStartLabel)
if (!languageVersionSettings.isReleaseCoroutines()) {
visitVarInsn(Opcodes.ALOAD, continuationIndex)
getfield(classBuilderForCoroutineState.thisName, EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_TYPE.descriptor)
visitVarInsn(Opcodes.ASTORE, exceptionIndex)
}
})
}
@@ -692,7 +654,7 @@ class CoroutineTransformerMethodVisitor(
// k + 1 - data
// k + 2 - exception
for (slot in 0 until localsCount) {
if (slot == continuationIndex || slot == dataIndex || slot == exceptionIndex) continue
if (slot == continuationIndex || slot == dataIndex) continue
val value = frame.getLocal(slot)
if (value.type == null || !livenessFrame.isAlive(slot)) continue
@@ -992,7 +954,7 @@ class CoroutineTransformerMethodVisitor(
insert(possibleTryCatchBlockStart, withInstructionAdapter {
nop()
generateResumeWithExceptionCheck(languageVersionSettings.isReleaseCoroutines(), dataIndex, exceptionIndex)
generateResumeWithExceptionCheck(dataIndex)
// Load continuation argument just like suspending function returns it
load(dataIndex, AsmTypes.OBJECT_TYPE)
@@ -1118,8 +1080,7 @@ internal fun InstructionAdapter.generateContinuationConstructorCall(
needDispatchReceiver: Boolean,
internalNameForDispatchReceiver: String?,
containingClassInternalName: String,
classBuilderForCoroutineState: ClassBuilder,
languageVersionSettings: LanguageVersionSettings
classBuilderForCoroutineState: ClassBuilder
) {
anew(objectTypeForState)
dup()
@@ -1128,8 +1089,7 @@ internal fun InstructionAdapter.generateContinuationConstructorCall(
getParameterTypesIndicesForCoroutineConstructor(
methodNode.desc,
methodNode.access,
needDispatchReceiver, internalNameForDispatchReceiver ?: containingClassInternalName,
languageVersionSettings
needDispatchReceiver, internalNameForDispatchReceiver ?: containingClassInternalName
)
for ((type, index) in parameterTypesAndIndices) {
load(index, type)
@@ -1149,22 +1109,11 @@ internal fun InstructionAdapter.generateContinuationConstructorCall(
)
}
private fun InstructionAdapter.generateResumeWithExceptionCheck(isReleaseCoroutines: Boolean, dataIndex: Int, exceptionIndex: Int) {
private fun InstructionAdapter.generateResumeWithExceptionCheck(dataIndex: Int) {
// Check if resumeWithException has been called
if (isReleaseCoroutines) {
load(dataIndex, AsmTypes.OBJECT_TYPE)
invokestatic("kotlin/ResultKt", "throwOnFailure", "(Ljava/lang/Object;)V", false)
} else {
load(exceptionIndex, AsmTypes.OBJECT_TYPE)
dup()
val noExceptionLabel = Label()
ifnull(noExceptionLabel)
athrow()
mark(noExceptionLabel)
pop()
}
load(dataIndex, AsmTypes.OBJECT_TYPE)
invokestatic("kotlin/ResultKt", "throwOnFailure", "(Ljava/lang/Object;)V", false)
}
private fun Type.fieldNameForVar(index: Int) = descriptor.first() + "$" + index
@@ -1235,16 +1184,15 @@ private fun getParameterTypesIndicesForCoroutineConstructor(
desc: String,
containingFunctionAccess: Int,
needDispatchReceiver: Boolean,
thisName: String,
languageVersionSettings: LanguageVersionSettings
thisName: String
): Collection<Pair<Type, Int>> {
return mutableListOf<Pair<Type, Int>>().apply {
if (needDispatchReceiver) {
add(Type.getObjectType(thisName) to 0)
}
val continuationIndex =
getAllParameterTypes(desc, !isStatic(containingFunctionAccess), thisName).dropLast(1).map(Type::getSize).sum()
add(languageVersionSettings.continuationAsmType() to continuationIndex)
getAllParameterTypes(desc, !isStatic(containingFunctionAccess), thisName).dropLast(1).sumOf(Type::getSize)
add(CONTINUATION_ASM_TYPE to continuationIndex)
}
}
@@ -1269,7 +1217,7 @@ private fun MethodNode.nodeTextWithLiveness(liveness: List<VariableLivenessFrame
* This means, that function parameters do not longer span the whole function, including `this`.
* This might and will break some bytecode processors, including old versions of R8. See KT-24510.
*/
private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction: Boolean) {
private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction: Boolean, suspensionPoints: List<LabelNode>) {
val liveness = analyzeLiveness(method)
fun List<LocalVariableNode>.findRecord(insnIndex: Int, variableIndex: Int): LocalVariableNode? {
@@ -1288,8 +1236,8 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
fun nextLabel(node: AbstractInsnNode?): LabelNode? {
var current = node
while (current != null) {
if (current is LabelNode) return current as LabelNode
current = current!!.next
if (current is LabelNode) return current
current = current.next
}
return null
}
@@ -1346,33 +1294,17 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
// Attempt to extend existing local variable node corresponding to the record in
// the original local variable table, if there is no back-edge
val recordToExtend: LocalVariableNode? = oldLvtNodeToLatestNewLvtNode[lvtRecord]
var recordExtended = false
if (recordToExtend != null) {
var hasBackEdgeOrStore = false
var current: AbstractInsnNode? = recordToExtend.end
while (current != null && current != endLabel) {
if (current is JumpInsnNode) {
if (method.instructions.indexOf((current as JumpInsnNode).label) < method.instructions.indexOf(current)) {
hasBackEdgeOrStore = true
break
}
}
if (current!!.isStoreOperation() && (current as VarInsnNode).`var` == recordToExtend.index) {
hasBackEdgeOrStore = true
break
}
current = current!!.next
}
if (!hasBackEdgeOrStore) {
recordToExtend.end = endLabel
recordExtended = true
}
}
if (!recordExtended) {
val node = LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
method.localVariables.add(node)
oldLvtNodeToLatestNewLvtNode[lvtRecord] = node
val latest = oldLvtNodeToLatestNewLvtNode[lvtRecord]
// if we can extend the previous range to where the local variable dies, we do not need a
// new entry, we know we cannot extend it to the lvt.endOffset, if we could we would have
// done so when we added it below.
val extended = latest?.extendRecordIfPossible(method, suspensionPoints, lvtRecord.end) ?: false
if (!extended) {
val new = LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
oldLvtNodeToLatestNewLvtNode[lvtRecord] = new
method.localVariables.add(new)
// see if we can extend it all the way to the old end
new.extendRecordIfPossible(method, suspensionPoints, lvtRecord.end)
}
}
}
@@ -1395,3 +1327,35 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
}
}
}
/* We cannot extend a record if there is STORE instruction or a back-edge.
* STORE instructions can signify a unspilling operation, in which case, the variable will become visible before it unspilled,
* back-edges occur in loops.
*
* @return true if the range has been extended
*/
private fun LocalVariableNode.extendRecordIfPossible(
method: MethodNode,
suspensionPoints: List<LabelNode>,
endLabel: LabelNode
): Boolean {
val nextSuspensionPointLabel = suspensionPoints.find { it in InsnSequence(end, endLabel) } ?: endLabel
var current: AbstractInsnNode? = end
while (current != null && current != nextSuspensionPointLabel) {
if (current is JumpInsnNode) {
if (method.instructions.indexOf(current.label) < method.instructions.indexOf(current)) {
return false
}
}
// TODO: HACK
// TODO: Find correct label, which is OK to be used as end label.
if (current.opcode == Opcodes.ARETURN && nextSuspensionPointLabel != endLabel) return false
if (current.isStoreOperation() && (current as VarInsnNode).`var` == index) {
return false
}
current = current.next
}
end = nextSuspensionPointLabel
return true
}

View File

@@ -88,18 +88,17 @@ class SuspendFunctionGenerationStrategy(
return CoroutineTransformerMethodVisitor(
mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState,
isForNamedFunction = true,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
disableTailCallOptimizationForFunctionReturningUnit = originalSuspendDescriptor.returnType?.isUnit() == true &&
originalSuspendDescriptor.overriddenDescriptors.isNotEmpty() &&
!originalSuspendDescriptor.allOverriddenFunctionsReturnUnit(),
reportSuspensionPointInsideMonitor = { reportSuspensionPointInsideMonitor(declaration, state, it) },
lineNumber = CodegenUtil.getLineNumberForElement(declaration, false) ?: 0,
sourceFile = declaration.containingKtFile.name,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null,
internalNameForDispatchReceiver = (originalSuspendDescriptor.containingDeclaration as? ClassDescriptor)?.let {
if (it.isInlineClass()) state.typeMapper.mapType(it).internalName else null
} ?: containingClassInternalNameOrNull(),
languageVersionSettings = languageVersionSettings,
disableTailCallOptimizationForFunctionReturningUnit = originalSuspendDescriptor.returnType?.isUnit() == true &&
originalSuspendDescriptor.overriddenDescriptors.isNotEmpty() &&
!originalSuspendDescriptor.allOverriddenFunctionsReturnUnit(),
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
)
}
@@ -155,8 +154,7 @@ class SuspendFunctionGenerationStrategy(
needDispatchReceiver,
internalNameForDispatchReceiver,
containingClassInternalName,
classBuilderForCoroutineState,
languageVersionSettings
classBuilderForCoroutineState
)
addFakeContinuationConstructorCallMarker(this, false)
pop() // Otherwise stack-transformation breaks

View File

@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Label
@@ -27,7 +26,6 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
internal class MethodNodeExaminer(
val languageVersionSettings: LanguageVersionSettings,
containingClassInternalName: String,
val methodNode: MethodNode,
suspensionPoints: List<SuspensionPoint>,
@@ -116,7 +114,7 @@ internal class MethodNodeExaminer(
val label = Label()
methodNode.instructions.insertBefore(pop, withInstructionAdapter {
dup()
loadCoroutineSuspendedMarker(languageVersionSettings)
loadCoroutineSuspendedMarker()
ifacmpne(label)
areturn(AsmTypes.OBJECT_TYPE)
mark(label)

View File

@@ -9,6 +9,8 @@ import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.common.COROUTINE_SUSPENDED_NAME
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalClassDescriptor
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
@@ -54,67 +56,27 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
const val COROUTINE_LABEL_FIELD_NAME = "label"
const val SUSPEND_FUNCTION_CREATE_METHOD_NAME = "create"
const val DO_RESUME_METHOD_NAME = "doResume"
const val INVOKE_SUSPEND_METHOD_NAME = "invokeSuspend"
const val EXCEPTION_FIELD_NAME = "exception"
const val CONTINUATION_RESULT_FIELD_NAME = "result"
val RELEASE_COROUTINES_VERSION_SETTINGS = LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3)
private const val GET_CONTEXT_METHOD_NAME = "getContext"
fun LanguageVersionSettings.isResumeImplMethodName(name: String) =
if (isReleaseCoroutines())
name == INVOKE_SUSPEND_METHOD_NAME
else
name == DO_RESUME_METHOD_NAME
val DEBUG_METADATA_ANNOTATION_ASM_TYPE: Type =
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("DebugMetadata")).topLevelClassAsmType()
fun LanguageVersionSettings.dataFieldName(): String = if (isReleaseCoroutines()) "result" else "data"
fun coroutineContextAsmType(): Type =
StandardNames.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineContext")).topLevelClassAsmType()
fun isResumeImplMethodNameFromAnyLanguageSettings(name: String) = name == INVOKE_SUSPEND_METHOD_NAME || name == DO_RESUME_METHOD_NAME
fun LanguageVersionSettings.coroutinesJvmInternalPackageFqName() =
coroutinesPackageFqName().child(Name.identifier("jvm")).child(Name.identifier("internal"))
val DEBUG_METADATA_ANNOTATION_ASM_TYPE = RELEASE_COROUTINES_VERSION_SETTINGS.coroutinesJvmInternalPackageFqName()
.child(Name.identifier("DebugMetadata")).topLevelClassAsmType()
fun LanguageVersionSettings.continuationAsmType() =
continuationInterfaceFqName().topLevelClassAsmType()
fun continuationAsmTypes() = listOf(
LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3).continuationAsmType(),
LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_2, ApiVersion.KOTLIN_1_2).continuationAsmType()
)
fun LanguageVersionSettings.coroutineContextAsmType() =
coroutinesPackageFqName().child(Name.identifier("CoroutineContext")).topLevelClassAsmType()
fun LanguageVersionSettings.isCoroutineSuperClass(internalName: String): Boolean {
val coroutinesJvmInternalPackage = coroutinesJvmInternalPackageFqName()
return if (isReleaseCoroutines())
coroutinesJvmInternalPackage.identifiedChild("ContinuationImpl") == internalName ||
coroutinesJvmInternalPackage.identifiedChild("RestrictedContinuationImpl") == internalName ||
coroutinesJvmInternalPackage.identifiedChild("SuspendLambda") == internalName ||
coroutinesJvmInternalPackage.identifiedChild("RestrictedSuspendLambda") == internalName
else
coroutinesJvmInternalPackage.identifiedChild("CoroutineImpl") == internalName
}
fun String.isCoroutineSuperClass(): Boolean =
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.identifiedChild("ContinuationImpl") == this ||
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.identifiedChild("RestrictedContinuationImpl") == this ||
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.identifiedChild("SuspendLambda") == this ||
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.identifiedChild("RestrictedSuspendLambda") == this
private fun FqName.identifiedChild(name: String) = child(Name.identifier(name)).topLevelClassInternalName()
private fun LanguageVersionSettings.coroutinesIntrinsicsFileFacadeInternalName() =
coroutinesIntrinsicsPackageFqName().child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType()
private fun LanguageVersionSettings.internalCoroutineIntrinsicsOwnerInternalName() =
coroutinesJvmInternalPackageFqName().child(Name.identifier("CoroutineIntrinsics")).topLevelClassInternalName()
fun computeLabelOwner(languageVersionSettings: LanguageVersionSettings, thisName: String): Type =
if (languageVersionSettings.isReleaseCoroutines())
Type.getObjectType(thisName)
else
languageVersionSettings.coroutinesJvmInternalPackageFqName().child(Name.identifier("CoroutineImpl")).topLevelClassAsmType()
private const val NORMALIZE_CONTINUATION_METHOD_NAME = "normalizeContinuation"
private const val GET_CONTEXT_METHOD_NAME = "getContext"
private val coroutinesIntrinsicsFileFacadeInternalName: Type =
COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType()
data class ResolvedCallWithRealDescriptor(val resolvedCall: ResolvedCall<*>, val fakeContinuationExpression: KtExpression)
@@ -122,7 +84,7 @@ data class ResolvedCallWithRealDescriptor(val resolvedCall: ResolvedCall<*>, val
val INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION = object : CallableDescriptor.UserDataKey<FunctionDescriptor> {}
@JvmField
val INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME = object : CallableDescriptor.UserDataKey<FunctionDescriptor> {}
val INITIAL_SUSPEND_DESCRIPTOR_FOR_INVOKE_SUSPEND = object : CallableDescriptor.UserDataKey<FunctionDescriptor> {}
val CONTINUATION_PARAMETER_NAME = Name.identifier("continuation")
@@ -158,9 +120,9 @@ fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
val newCandidateDescriptor =
when (function) {
is FunctionImportedFromObject ->
getOrCreateJvmSuspendFunctionView(function.callableFromObject, isReleaseCoroutines, bindingContext).asImportedFromObject()
getOrCreateJvmSuspendFunctionView(function.callableFromObject, bindingContext).asImportedFromObject()
is SimpleFunctionDescriptor ->
getOrCreateJvmSuspendFunctionView(function, isReleaseCoroutines, bindingContext)
getOrCreateJvmSuspendFunctionView(function, bindingContext)
else ->
throw AssertionError("Unexpected suspend function descriptor: $function")
}
@@ -223,10 +185,10 @@ private fun NewResolvedCallImpl<VariableDescriptor>.asDummyOldResolvedCall(bindi
enum class SuspensionPointKind { NEVER, NOT_INLINE, ALWAYS }
fun ResolvedCall<*>.isSuspensionPoint(codegen: ExpressionCodegen, languageVersionSettings: LanguageVersionSettings): SuspensionPointKind {
fun ResolvedCall<*>.isSuspensionPoint(codegen: ExpressionCodegen): SuspensionPointKind {
val functionDescriptor = resultingDescriptor as? FunctionDescriptor ?: return SuspensionPointKind.NEVER
if (!functionDescriptor.unwrapInitialDescriptorForSuspendFunction().isSuspend) return SuspensionPointKind.NEVER
if (functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm(languageVersionSettings)) return SuspensionPointKind.ALWAYS
if (functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm()) return SuspensionPointKind.ALWAYS
if (functionDescriptor.isInline) return SuspensionPointKind.NEVER
val isInlineLambda = this.safeAs<VariableAsFunctionResolvedCall>()
@@ -242,7 +204,6 @@ fun CallableDescriptor.isSuspendFunctionNotSuspensionView(): Boolean {
fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(function: D, state: GenerationState): D = getOrCreateJvmSuspendFunctionView(
function,
state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines),
state.bindingContext
)
@@ -252,7 +213,6 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(function: D, stat
@JvmOverloads
fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
function: D,
isReleaseCoroutines: Boolean,
bindingContext: BindingContext? = null
): D {
assert(function.isSuspend) {
@@ -272,7 +232,7 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
outType = if (function.containingDeclaration.safeAs<ClassDescriptor>()?.isBuiltinFunctionalClassDescriptor == true)
function.builtIns.nullableAnyType
else
function.getContinuationParameterTypeOfSuspendFunction(isReleaseCoroutines),
function.getContinuationParameterTypeOfSuspendFunction(),
declaresDefaultValue = false, isCrossinline = false,
isNoinline = false, varargElementType = null,
source = SourceElement.NO_SOURCE
@@ -309,8 +269,7 @@ fun <D : FunctionDescriptor> D.createCustomCopy(
return result as D
}
private fun FunctionDescriptor.getContinuationParameterTypeOfSuspendFunction(isReleaseCoroutines: Boolean) =
module.getContinuationOfTypeOrAny(returnType!!, if (this.needsExperimentalCoroutinesWrapper()) false else isReleaseCoroutines)
private fun FunctionDescriptor.getContinuationParameterTypeOfSuspendFunction() = module.getContinuationOfTypeOrAny(returnType!!)
fun ModuleDescriptor.getResult(kotlinType: KotlinType) =
module.resolveTopLevelClass(
@@ -323,44 +282,11 @@ fun ModuleDescriptor.getResult(kotlinType: KotlinType) =
)
} ?: ErrorUtils.createErrorType("For Result")
private fun MethodNode.invokeNormalizeContinuation(languageVersionSettings: LanguageVersionSettings) {
visitMethodInsn(
Opcodes.INVOKESTATIC,
languageVersionSettings.internalCoroutineIntrinsicsOwnerInternalName(),
NORMALIZE_CONTINUATION_METHOD_NAME,
Type.getMethodDescriptor(languageVersionSettings.continuationAsmType(), languageVersionSettings.continuationAsmType()),
false
)
}
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm() =
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineUninterceptedOrReturn() == true
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm(languageVersionSettings: LanguageVersionSettings) =
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) == true
fun createMethodNodeForIntercepted(languageVersionSettings: LanguageVersionSettings): MethodNode {
val node =
MethodNode(
Opcodes.API_VERSION,
Opcodes.ACC_STATIC,
"fake",
Type.getMethodDescriptor(languageVersionSettings.continuationAsmType(), languageVersionSettings.continuationAsmType()),
null, null
)
node.visitVarInsn(Opcodes.ALOAD, 0)
node.invokeNormalizeContinuation(languageVersionSettings)
node.visitInsn(Opcodes.ARETURN)
node.visitMaxs(1, 1)
return node
}
fun createMethodNodeForCoroutineContext(
functionDescriptor: FunctionDescriptor,
languageVersionSettings: LanguageVersionSettings
): MethodNode {
assert(functionDescriptor.isBuiltInCoroutineContext(languageVersionSettings)) {
fun createMethodNodeForCoroutineContext(functionDescriptor: FunctionDescriptor): MethodNode {
assert(functionDescriptor.isBuiltInCoroutineContext()) {
"functionDescriptor must be kotlin.coroutines.intrinsics.coroutineContext property getter"
}
@@ -369,7 +295,7 @@ fun createMethodNodeForCoroutineContext(
Opcodes.API_VERSION,
Opcodes.ACC_STATIC,
"fake",
Type.getMethodDescriptor(languageVersionSettings.coroutineContextAsmType()),
Type.getMethodDescriptor(coroutineContextAsmType()),
null, null
)
@@ -377,20 +303,20 @@ fun createMethodNodeForCoroutineContext(
addFakeContinuationMarker(v)
v.invokeGetContext(languageVersionSettings)
v.invokeGetContext()
node.visitMaxs(1, 1)
return node
}
fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSettings: LanguageVersionSettings): MethodNode {
fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(): MethodNode {
val node =
MethodNode(
Opcodes.API_VERSION,
Opcodes.ACC_STATIC,
"fake",
Type.getMethodDescriptor(OBJECT_TYPE, AsmTypes.FUNCTION1, languageVersionSettings.continuationAsmType()),
Type.getMethodDescriptor(OBJECT_TYPE, AsmTypes.FUNCTION1, CONTINUATION_ASM_TYPE),
null, null
)
@@ -405,25 +331,22 @@ fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSett
"($OBJECT_TYPE)$OBJECT_TYPE"
)
if (languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)) {
val elseLabel = Label()
// if (result === COROUTINE_SUSPENDED) {
dup()
loadCoroutineSuspendedMarker(languageVersionSettings)
ifacmpne(elseLabel)
// DebugProbesKt.probeCoroutineSuspended(continuation)
load(1, OBJECT_TYPE) // continuation
checkcast(languageVersionSettings.continuationAsmType())
invokestatic(
languageVersionSettings.coroutinesJvmInternalPackageFqName().child(Name.identifier("DebugProbesKt"))
.topLevelClassAsmType().internalName,
"probeCoroutineSuspended",
"(${languageVersionSettings.continuationAsmType()})V",
false
)
// }
mark(elseLabel)
}
val elseLabel = Label()
// if (result === COROUTINE_SUSPENDED) {
dup()
loadCoroutineSuspendedMarker()
ifacmpne(elseLabel)
// DebugProbesKt.probeCoroutineSuspended(continuation)
load(1, OBJECT_TYPE) // continuation
checkcast(CONTINUATION_ASM_TYPE)
invokestatic(
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("DebugProbesKt")).topLevelClassAsmType().internalName,
"probeCoroutineSuspended",
"($CONTINUATION_ASM_TYPE)V",
false
)
// }
mark(elseLabel)
}
node.visitInsn(Opcodes.ARETURN)
@@ -433,13 +356,13 @@ fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSett
}
private fun InstructionAdapter.invokeGetContext(languageVersionSettings: LanguageVersionSettings) {
private fun InstructionAdapter.invokeGetContext() {
invokeinterface(
languageVersionSettings.continuationAsmType().internalName,
CONTINUATION_ASM_TYPE.internalName,
GET_CONTEXT_METHOD_NAME,
Type.getMethodDescriptor(languageVersionSettings.coroutineContextAsmType())
Type.getMethodDescriptor(coroutineContextAsmType())
)
areturn(languageVersionSettings.coroutineContextAsmType())
areturn(coroutineContextAsmType())
}
@Suppress("UNCHECKED_CAST")
@@ -447,15 +370,12 @@ fun <D : CallableDescriptor?> D.unwrapInitialDescriptorForSuspendFunction(): D =
this.safeAs<SimpleFunctionDescriptor>()?.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) as D ?: this
fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext, isReleaseCoroutines: Boolean): FunctionDescriptor =
fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext): FunctionDescriptor =
if (isSuspend)
getOrCreateJvmSuspendFunctionView(unwrapInitialDescriptorForSuspendFunction().original, isReleaseCoroutines, bindingContext)
getOrCreateJvmSuspendFunctionView(unwrapInitialDescriptorForSuspendFunction().original, bindingContext)
else
this
fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext, state: GenerationState) =
getOriginalSuspendFunctionView(bindingContext, state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))
// For each suspend function, we have a corresponding JVM view function that has an extra continuation parameter,
// and, more importantly, returns 'kotlin.Any' (so that it can return as a reference value or a special COROUTINE_SUSPENDED object).
// This also causes boxing of primitives and inline class values.
@@ -482,38 +402,24 @@ fun FunctionDescriptor.originalReturnTypeOfSuspendFunctionReturningUnboxedInline
return originalReturnType
}
fun InstructionAdapter.loadCoroutineSuspendedMarker(languageVersionSettings: LanguageVersionSettings) {
fun InstructionAdapter.loadCoroutineSuspendedMarker() {
invokestatic(
languageVersionSettings.coroutinesIntrinsicsFileFacadeInternalName().internalName,
coroutinesIntrinsicsFileFacadeInternalName.internalName,
"get$COROUTINE_SUSPENDED_NAME",
Type.getMethodDescriptor(OBJECT_TYPE),
false
)
}
fun InstructionAdapter.generateCoroutineSuspendedCheck(languageVersionSettings: LanguageVersionSettings) {
fun InstructionAdapter.generateCoroutineSuspendedCheck() {
dup()
loadCoroutineSuspendedMarker(languageVersionSettings)
loadCoroutineSuspendedMarker()
val elseLabel = Label()
ifacmpne(elseLabel)
areturn(OBJECT_TYPE)
mark(elseLabel)
}
fun InstructionAdapter.invokeDoResumeWithUnit(thisName: String) {
// .doResume(Unit, null)
StackValue.putUnitInstance(this)
aconst(null)
invokevirtual(
thisName,
DO_RESUME_METHOD_NAME,
Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE, AsmTypes.JAVA_THROWABLE_TYPE),
false
)
}
fun InstructionAdapter.invokeInvokeSuspendWithUnit(thisName: String) {
StackValue.putUnitInstance(this)
@@ -537,18 +443,14 @@ fun FunctionDescriptor.isSuspendLambdaOrLocalFunction() = this.isSuspend && when
}
fun FunctionDescriptor.isLocalSuspendFunctionNotSuspendLambda() = isSuspendLambdaOrLocalFunction() && this !is AnonymousFunctionDescriptor
@JvmField
val EXPERIMENTAL_CONTINUATION_ASM_TYPE = StandardNames.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL.topLevelClassAsmType()
@JvmField
val RELEASE_CONTINUATION_ASM_TYPE = StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE.topLevelClassAsmType()
val CONTINUATION_ASM_TYPE = StandardNames.CONTINUATION_INTERFACE_FQ_NAME.topLevelClassAsmType()
fun FunctionDescriptor.isInvokeSuspendOfLambda(): Boolean {
if (this !is SimpleFunctionDescriptor) return false
if (valueParameters.size != 1 ||
valueParameters[0].name.asString() != SUSPEND_CALL_RESULT_NAME ||
name.asString() != "invokeSuspend"
name.asString() != INVOKE_SUSPEND_METHOD_NAME
) return false
return containingDeclaration is SyntheticClassDescriptorForLambda
}

View File

@@ -62,7 +62,7 @@ class AnonymousObjectTransformer(
createClassReader().accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) {
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
classBuilder.defineClass(null, maxOf(version, state.classFileVersion), access, name, signature, superName, interfaces)
if (languageVersionSettings.isCoroutineSuperClass(superName)) {
if (superName.isCoroutineSuperClass()) {
inliningContext.isContinuation = true
}
superClassName = superName

View File

@@ -0,0 +1,386 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.optimization.boxing.isMethodInsnWith
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
import org.jetbrains.kotlin.codegen.optimization.common.removeUnusedLocalVariables
import org.jetbrains.kotlin.codegen.optimization.common.updateMaxStack
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.*
class InplaceArgumentsMethodTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
val methodContext = parseMethodOrNull(methodNode)
if (methodContext != null) {
if (methodContext.calls.isEmpty()) return
collectStartToEnd(methodContext)
collectLvtEntryInstructions(methodContext)
collectSuspensionPoints(methodContext)
transformMethod(methodContext)
updateLvtEntriesForMovedInstructions(methodContext)
methodNode.removeUnusedLocalVariables()
methodNode.updateMaxStack()
}
stripMarkers(methodNode)
}
private class MethodContext(
val methodNode: MethodNode,
val calls: List<CallContext>
) {
val startArgToEndArg = HashMap<AbstractInsnNode, AbstractInsnNode>()
val lvtEntryForInstruction = HashMap<AbstractInsnNode, LocalVariableNode>()
val varInstructionMoved = HashMap<AbstractInsnNode, CallContext>()
val suspensionJumpLabels = HashSet<LabelNode>()
}
private class CallContext(
val callStartMarker: AbstractInsnNode,
val callEndMarker: AbstractInsnNode,
val args: List<ArgContext>,
val calls: List<CallContext>,
val endLabel: LabelNode
)
private class ArgContext(
val argStartMarker: AbstractInsnNode,
val argEndMarker: AbstractInsnNode,
val calls: List<CallContext>,
val storeInsn: VarInsnNode
) {
val loadOpcode = storeInsn.opcode - Opcodes.ISTORE + Opcodes.ILOAD
val varIndex = storeInsn.`var`
}
private fun parseMethodOrNull(methodNode: MethodNode): MethodContext? {
// We assume that the method body structure follows this grammar:
// METHOD ::= insn* (CALL insn*)*
// CALL ::= callStartMarker insn* (ARG insn*)* (CALL insn*)* callEndMarker
// ARG ::= argStartMarker insn* (CALL insn*)* argEndMarker storeInsn
val iter = methodNode.instructions.iterator()
val calls = ArrayList<CallContext>()
try {
while (iter.hasNext()) {
val insn = iter.next()
when {
insn.isInplaceCallStartMarker() ->
calls.add(parseCall(methodNode, insn, iter))
insn.isInplaceCallEndMarker() || insn.isInplaceArgumentStartMarker() || insn.isInplaceArgumentEndMarker() ->
throw ParseErrorException()
}
}
} catch (e: ParseErrorException) {
return null
}
return MethodContext(methodNode, calls)
}
private fun parseCall(methodNode: MethodNode, start: AbstractInsnNode, iter: ListIterator<AbstractInsnNode>): CallContext {
// CALL ::= callStartMarker insn* (ARG insn*)* (CALL insn*)* callEndMarker
val args = ArrayList<ArgContext>()
val calls = ArrayList<CallContext>()
while (iter.hasNext()) {
val insn = iter.next()
when {
insn.isInplaceCallStartMarker() ->
calls.add(parseCall(methodNode, insn, iter))
insn.isInplaceCallEndMarker() -> {
val previous = insn.previous
val endLabel =
if (previous.type == AbstractInsnNode.LABEL)
previous as LabelNode
else
LabelNode(Label()).also {
// Make sure each call with inplace arguments has an endLabel
// (we need it to update LVT after transformation).
methodNode.instructions.insertBefore(insn, it)
}
return CallContext(start, insn, args, calls, endLabel)
}
insn.isInplaceArgumentStartMarker() ->
args.add(parseArg(methodNode, insn, iter))
insn.isInplaceArgumentEndMarker() ->
throw ParseErrorException()
}
}
// Reached instruction list end, didn't find inplace-call-end marker
throw ParseErrorException()
}
private fun parseArg(methodNode: MethodNode, start: AbstractInsnNode, iter: ListIterator<AbstractInsnNode>): ArgContext {
// ARG ::= argStartMarker insn* (CALL insn*)* argEndMarker storeInsn
val calls = ArrayList<CallContext>()
while (iter.hasNext()) {
val insn = iter.next()
when {
insn.isInplaceCallStartMarker() ->
calls.add(parseCall(methodNode, insn, iter))
insn.isInplaceArgumentEndMarker() -> {
val next = insn.next
if (next is VarInsnNode && next.opcode in Opcodes.ISTORE..Opcodes.ASTORE) {
iter.next()
return ArgContext(start, insn, calls, next)
} else {
throw ParseErrorException()
}
}
insn.isInplaceCallEndMarker() || insn.isInplaceArgumentStartMarker() ->
throw ParseErrorException()
}
}
// Reached instruction list end, didn't find inplace-argument-end marker
throw ParseErrorException()
}
private class ParseErrorException : RuntimeException() {
override fun fillInStackTrace(): Throwable = this
}
private fun collectStartToEnd(methodContext: MethodContext) {
for (call in methodContext.calls) {
collectStartToEnd(methodContext, call)
}
}
private fun collectStartToEnd(methodContext: MethodContext, callContext: CallContext) {
for (arg in callContext.args) {
collectStartToEnd(methodContext, arg)
}
for (call in callContext.calls) {
collectStartToEnd(methodContext, call)
}
}
private fun collectStartToEnd(methodContext: MethodContext, argContext: ArgContext) {
methodContext.startArgToEndArg[argContext.argStartMarker] = argContext.argEndMarker
for (call in argContext.calls) {
collectStartToEnd(methodContext, call)
}
}
private fun collectLvtEntryInstructions(methodContext: MethodContext) {
val insnList = methodContext.methodNode.instructions
val insnArray = insnList.toArray()
for (lv in methodContext.methodNode.localVariables) {
val lvStartIndex = insnList.indexOf(lv.start)
val lvEndIndex = insnList.indexOf(lv.end)
for (i in lvStartIndex until lvEndIndex) {
val insn = insnArray[i]
if (insn.opcode in Opcodes.ILOAD..Opcodes.ALOAD || insn.opcode in Opcodes.ISTORE..Opcodes.ASTORE) {
if ((insn as VarInsnNode).`var` == lv.index) {
methodContext.lvtEntryForInstruction[insn] = lv
}
} else if (insn.opcode == Opcodes.IINC) {
if ((insn as IincInsnNode).`var` == lv.index) {
methodContext.lvtEntryForInstruction[insn] = lv
}
}
}
}
}
private fun collectSuspensionPoints(methodContext: MethodContext) {
val insnList = methodContext.methodNode.instructions
var insn = insnList.first
while (
!insn.isMethodInsnWith(Opcodes.INVOKESTATIC) {
owner == "kotlin/coroutines/intrinsics/IntrinsicsKt" &&
name == "getCOROUTINE_SUSPENDED" &&
desc == "()Ljava/lang/Object;"
}
) {
insn = insn.next ?: return
}
// Find a first TABLESWITCH and record its jump destinations
while (insn != null) {
if (insn.opcode != Opcodes.TABLESWITCH || insn.previous.opcode != Opcodes.GETFIELD) {
insn = insn.next
continue
}
val getFiendInsn = insn.previous as FieldInsnNode
if (getFiendInsn.name != "label" || getFiendInsn.desc != "I") {
insn = insn.next
continue
}
val tableSwitchInsn = insn as TableSwitchInsnNode
methodContext.suspensionJumpLabels.addAll(tableSwitchInsn.labels)
methodContext.suspensionJumpLabels.add(tableSwitchInsn.dflt)
return
}
}
private fun transformMethod(methodContext: MethodContext) {
for (call in methodContext.calls) {
transformCall(methodContext, call)
}
}
private fun transformCall(methodContext: MethodContext, callContext: CallContext) {
// Transform nested calls
for (arg in callContext.args) {
for (nestedCall in arg.calls) {
transformCall(methodContext, nestedCall)
}
}
for (call in callContext.calls) {
transformCall(methodContext, call)
}
// If an inplace argument contains a non-local jump,
// moving such argument inside inline function body can interfere with stack normalization.
// TODO investigate complex cases
if (callContext.args.any { it.isUnsafeToMove(methodContext) }) {
// Do not transform such call, just strip call and argument markers.
val insnList = methodContext.methodNode.instructions
for (arg in callContext.args) {
insnList.remove(arg.argStartMarker)
insnList.remove(arg.argEndMarker)
}
insnList.remove(callContext.callStartMarker)
insnList.remove(callContext.callEndMarker)
return
}
moveInplaceArgumentsFromStoresToLoads(methodContext, callContext)
}
private fun ArgContext.isUnsafeToMove(methodContext: MethodContext): Boolean {
val argInsns = InsnSequence(this.argStartMarker, this.argEndMarker)
val localLabels = argInsns.filterTo(HashSet()) { it is LabelNode }
return argInsns.any { insn ->
insn in methodContext.suspensionJumpLabels ||
insn.opcode == Opcodes.GOTO && (insn as JumpInsnNode).label !in localLabels
}
}
private fun moveInplaceArgumentsFromStoresToLoads(methodContext: MethodContext, callContext: CallContext) {
// Transform call
val insnList = methodContext.methodNode.instructions
val args = callContext.args.associateBy { it.varIndex }
var argsProcessed = 0
var insn: AbstractInsnNode = callContext.callStartMarker
while (insn != callContext.callEndMarker) {
when {
insn.isInplaceArgumentStartMarker() -> {
// Skip argument body
insn = methodContext.startArgToEndArg[insn]!!
}
insn.opcode in Opcodes.ILOAD..Opcodes.ALOAD -> {
// Load instruction
val loadInsn = insn as VarInsnNode
val varIndex = loadInsn.`var`
val arg = args[varIndex]
if (arg == null || arg.loadOpcode != insn.opcode) {
// Not an argument load
insn = insn.next
} else {
// For each argument within this call we have
// <inplaceArgStartMarker>
// <argumentBody>
// <inplaceArgEndMarker>
// store [arg]
// ...
// load [arg]
// Replace 'load [arg]' with '<argumentBody>', drop 'store [arg]' and argument markers.
var argInsn = arg.argStartMarker.next
while (argInsn != arg.argEndMarker) {
// If a LOAD/STORE/IINC instruction was moved,
// record it so that we can update corresponding LVT entry if needed.
// NB it's better to do so after all transformations, so that we don't recalculate node indices.
if (argInsn.opcode in Opcodes.ILOAD..Opcodes.ALOAD ||
argInsn.opcode in Opcodes.ISTORE..Opcodes.ASTORE ||
argInsn.opcode == Opcodes.IINC
) {
methodContext.varInstructionMoved[argInsn] = callContext
}
val argInsnNext = argInsn.next
insnList.remove(argInsn)
insnList.insertBefore(loadInsn, argInsn)
argInsn = argInsnNext
}
// Remove argument load and corresponding argument store instructions
insnList.remove(arg.storeInsn)
insn = loadInsn.next
insnList.remove(loadInsn)
// Replace subsequent argument loads with DUP instructions of appropriate size
while (insn.opcode == loadInsn.opcode && (insn as VarInsnNode).`var` == varIndex) {
if (insn.opcode == Opcodes.LLOAD || insn.opcode == Opcodes.DLOAD) {
insnList.insertBefore(insn, InsnNode(Opcodes.DUP2))
} else {
insnList.insertBefore(insn, InsnNode(Opcodes.DUP))
}
val next = insn.next
insnList.remove(insn)
insn = next
}
// Remove argument markers
insnList.remove(arg.argStartMarker)
insnList.remove(arg.argEndMarker)
// If there are no more inplace arguments left to process, we are done
++argsProcessed
if (argsProcessed >= callContext.args.size)
break
}
}
else ->
insn = insn.next
}
}
// Remove call start and call end markers
insnList.remove(callContext.callStartMarker)
insnList.remove(callContext.callEndMarker)
}
private fun updateLvtEntriesForMovedInstructions(methodContext: MethodContext) {
val insnList = methodContext.methodNode.instructions
for ((insn, callContext) in methodContext.varInstructionMoved.entries) {
// Extend local variable interval to call end label if needed
val lv = methodContext.lvtEntryForInstruction[insn] ?: continue
val lvEndIndex = insnList.indexOf(lv.end)
val endLabelIndex = insnList.indexOf(callContext.endLabel)
if (endLabelIndex > lvEndIndex) {
lv.end = callContext.endLabel
}
}
}
private fun stripMarkers(methodNode: MethodNode) {
var insn = methodNode.instructions.first
while (insn != null) {
if (insn.isInplaceCallStartMarker() ||
insn.isInplaceCallEndMarker() ||
insn.isInplaceArgumentStartMarker() ||
insn.isInplaceArgumentEndMarker()
) {
val next = insn.next
methodNode.instructions.remove(insn)
insn = next
continue
}
insn = insn.next
}
}
}

View File

@@ -104,7 +104,7 @@ class DefaultLambda(info: ExtractedDefaultLambda, sourceCompiler: SourceCompiler
// TODO: suspend lambdas are their own continuations, so the body is pre-inlined into `invokeSuspend`
// and thus can't be detangled from the state machine. To make them inlinable, this needs to be redesigned.
// See `SuspendLambdaLowering`.
require(!sourceCompiler.state.languageVersionSettings.isCoroutineSuperClass(superName)) {
require(!superName.isCoroutineSuperClass()) {
"suspend default lambda ${lambdaClassType.internalName} cannot be inlined; use a function reference instead"
}

View File

@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.coroutines.continuationAsmType
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_ASM_TYPE
import org.jetbrains.kotlin.codegen.inline.FieldRemapper.Companion.foldName
import org.jetbrains.kotlin.codegen.inline.coroutines.CoroutineTransformer
import org.jetbrains.kotlin.codegen.inline.coroutines.markNoinlineLambdaIfSuspend
@@ -688,7 +688,7 @@ class MethodInliner(
}
for ((index, param) in paramTypes.reversed().withIndex()) {
if (param != languageVersionSettings.continuationAsmType() && param != OBJECT_TYPE) continue
if (param != CONTINUATION_ASM_TYPE && param != OBJECT_TYPE) continue
val sourceIndices = (frame.getStack(frame.stackSize - index - 1) as? Aload0BasicValue)?.indices ?: continue
for (sourceIndex in sourceIndices) {
val src = processingNode.instructions[sourceIndex]
@@ -733,6 +733,7 @@ class MethodInliner(
private fun preprocessNodeBeforeInline(node: MethodNode, returnLabels: Map<String, Label?>) {
try {
InplaceArgumentsMethodTransformer().transform("fake", node)
FixStackWithLabelNormalizationMethodTransformer().transform("fake", node)
} catch (e: Throwable) {
throw wrapException(e, node, "couldn't inline method call")

View File

@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.psi.*
@@ -158,8 +157,7 @@ class PsiSourceCompilerForInline(
}
FunctionCodegen.generateMethodBody(
adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen, state.jvmDefaultMode,
state.languageVersionSettings.isReleaseCoroutines()
adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen, state.jvmDefaultMode
)
if (isLambda) {
@@ -235,7 +233,7 @@ class PsiSourceCompilerForInline(
}
override fun compileInlineFunction(jvmSignature: JvmMethodSignature): SMAPAndMethodNode {
generateInlineIntrinsic(state.languageVersionSettings, functionDescriptor, jvmSignature.asmMethod, codegen.typeSystem)?.let {
generateInlineIntrinsic(functionDescriptor, jvmSignature.asmMethod, codegen.typeSystem)?.let {
return it
}

View File

@@ -22,8 +22,6 @@ import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.codegen.optimization.common.intConstant
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.types.KotlinType
@@ -233,7 +231,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
if (stubCheckcast !is TypeInsnNode) return false
val newMethodNode = MethodNode(Opcodes.API_VERSION)
generateAsCast(InstructionAdapter(newMethodNode), kotlinType, asmType, safe, languageVersionSettings, unifiedNullChecks)
generateAsCast(InstructionAdapter(newMethodNode), kotlinType, asmType, safe, unifiedNullChecks)
instructions.insert(insn, newMethodNode.instructions)
// Keep stubCheckcast to avoid VerifyErrors on 1.8+ bytecode,
@@ -257,7 +255,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
if (stubInstanceOf !is TypeInsnNode) return false
val newMethodNode = MethodNode(Opcodes.API_VERSION)
generateIsCheck(InstructionAdapter(newMethodNode), kotlinType, asmType, languageVersionSettings.isReleaseCoroutines())
generateIsCheck(InstructionAdapter(newMethodNode), kotlinType, asmType)
instructions.insert(insn, newMethodNode.instructions)
instructions.remove(stubInstanceOf)

View File

@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.org.objectweb.asm.MethodVisitor
@@ -49,18 +48,16 @@ class CoroutineTransformer(
fun suspendLambdaWithGeneratedStateMachine(node: MethodNode): Boolean =
!isContinuationNotLambda() && isSuspendLambda(node) && isStateMachine(node)
private fun isContinuationNotLambda(): Boolean = inliningContext.isContinuation &&
if (state.languageVersionSettings.isReleaseCoroutines()) superClassName.endsWith("ContinuationImpl")
else methods.any { it.name == "getLabel" }
private fun isContinuationNotLambda(): Boolean = inliningContext.isContinuation && superClassName.endsWith("ContinuationImpl")
private fun isStateMachine(node: MethodNode): Boolean =
node.instructions.asSequence().any { insn -> insn is LdcInsnNode && insn.cst == ILLEGAL_STATE_ERROR_MESSAGE }
private fun isSuspendLambda(node: MethodNode) = isResumeImpl(node)
private fun isSuspendLambda(node: MethodNode) = isInvokeSuspend(node)
fun newMethod(node: MethodNode): DeferredMethodVisitor {
return when {
isResumeImpl(node) -> {
isInvokeSuspend(node) -> {
assert(!isStateMachine(node)) {
"Inlining/transforming state-machine"
}
@@ -71,9 +68,8 @@ class CoroutineTransformer(
}
}
private fun isResumeImpl(node: MethodNode): Boolean =
state.languageVersionSettings.isResumeImplMethodName(node.name.removeSuffix(FOR_INLINE_SUFFIX)) &&
inliningContext.isContinuation
private fun isInvokeSuspend(node: MethodNode): Boolean =
node.name.removeSuffix(FOR_INLINE_SUFFIX) == INVOKE_SUSPEND_METHOD_NAME && inliningContext.isContinuation
private fun isSuspendFunctionWithFakeConstructorCall(node: MethodNode): Boolean = findFakeContinuationConstructorClassName(node) != null
@@ -88,16 +84,15 @@ class CoroutineTransformer(
val sourceCompilerForInline = inliningContext.root.sourceCompilerForInline
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
containingClassInternalName = classBuilder.thisName,
obtainClassBuilderForCoroutineState = { classBuilder },
isForNamedFunction = false,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
disableTailCallOptimizationForFunctionReturningUnit = false,
reportSuspensionPointInsideMonitor = { sourceCompilerForInline.reportSuspensionPointInsideMonitor(it) },
// TODO: this linenumbers might not be correct and since they are used only for step-over, check them.
lineNumber = inliningContext.callSiteInfo.lineNumber,
sourceFile = inliningContext.callSiteInfo.file?.name ?: "",
languageVersionSettings = state.languageVersionSettings,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = classBuilder.thisName,
isForNamedFunction = false,
disableTailCallOptimizationForFunctionReturningUnit = false,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
)
@@ -123,17 +118,16 @@ class CoroutineTransformer(
val sourceCompilerForInline = inliningContext.root.sourceCompilerForInline
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
containingClassInternalName = classBuilder.thisName,
obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! },
isForNamedFunction = true,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
disableTailCallOptimizationForFunctionReturningUnit = disableTailCallOptimization,
reportSuspensionPointInsideMonitor = { sourceCompilerForInline.reportSuspensionPointInsideMonitor(it) },
lineNumber = inliningContext.callSiteInfo.lineNumber,
sourceFile = inliningContext.callSiteInfo.file?.name ?: "",
languageVersionSettings = state.languageVersionSettings,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = classBuilder.thisName,
isForNamedFunction = true,
needDispatchReceiver = true,
internalNameForDispatchReceiver = classBuilder.thisName,
disableTailCallOptimizationForFunctionReturningUnit = disableTailCallOptimization,
putContinuationParameterToLvt = !state.isIrBackend,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
)

View File

@@ -0,0 +1,223 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isParameterCheckedForNull
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.tree.*
fun canInlineArgumentsInPlace(methodNode: MethodNode): Boolean {
// Usual inline functions are inlined in the following way:
// <evaluate argument #1>
// <store argument to an argument variable V1>
// ...
// <evaluate argument #N>
// <store argument to an argument variable VN>
// <inline function method body with parameter variables Pi remapped to argument variables Vi>
// If an argument #k is already stored in a local variable W, this variable W is reused.
// When inlining arguments in-place, we instead replace corresponding variable load instructions in the inline function method body
// with bytecode for evaluating a given argument.
// We can do so if such transformation keeps the evaluation order intact, possibly disregarding class initialization.
//
// This is true for many simple @InlineOnly functions from Kotlin standard library.
// For example, bytecode for 'inline fun println(message: Any?)' is:
// GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
// ALOAD 0
// INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
// Basic inlining for 'println("Hello, world!")' would produce (skipping labels and line numbers):
// // evaluate arguments, storing them to local variables
// LDC "Hello, world!"
// ASTORE 0
// GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
// ALOAD 0
// INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
// With argument "Hello, world!" inlined in-place it would be:
// GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
// LDC "Hello, world!"
// INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
// Such inlining is possible because we consider it OK to reorder 'GETSTATIC java/lang/System.out : Ljava/io/PrintStream;' instruction
// with any argument evaluation instructions ('LDC "Hello, world!"' in this case).
val tcbStartLabels = methodNode.tryCatchBlocks.mapTo(HashSet()) { it.start }
val methodParameterTypes = Type.getArgumentTypes(methodNode.desc)
val jvmArgumentTypes = ArrayList<Type>(methodParameterTypes.size + 1)
if (methodNode.access and Opcodes.ACC_STATIC == 0) {
// Here we don't care much about the exact 'this' type,
// it's only important to remember that variable slot #0 holds an object reference.
jvmArgumentTypes.add(AsmTypes.OBJECT_TYPE)
}
jvmArgumentTypes.addAll(methodParameterTypes)
val argumentVarEnd = jvmArgumentTypes.sumOf { it.size }
var expectedArgumentVar = 0
var lastArgIndex = 0
var insn = methodNode.instructions.first
// During arguments evaluation, make sure that all arguments are loaded in expected order
// and there are no unexpected side effects in-between.
while (insn != null && expectedArgumentVar < argumentVarEnd) {
// Entering a try-catch block before all arguments are loaded breaks evaluation order.
if (insn in tcbStartLabels)
return false
// Some instructions break evaluation order.
if (insn.isProhibitedDuringArgumentsEvaluation())
return false
// Allow a limited list of 'GETSTATIC <owner> <name> <desc>' instructions.
if (insn.opcode == Opcodes.GETSTATIC) {
val fieldInsn = insn as FieldInsnNode
val fieldSignature = FieldSignature(fieldInsn.owner, fieldInsn.name, fieldInsn.desc)
if (fieldSignature !in whitelistedStaticFields)
return false
}
// Writing to or incrementing an argument variable forbids in-place argument inlining.
if (insn.opcode in Opcodes.ISTORE..Opcodes.ASTORE && (insn as VarInsnNode).`var` < argumentVarEnd)
return false
if (insn.opcode == Opcodes.IINC && (insn as IincInsnNode).`var` < argumentVarEnd)
return false
// Analyze variable loads.
if (insn.opcode in Opcodes.ILOAD..Opcodes.ALOAD) {
// Skip parameter null check: 'aload x; ldc "..."; invokestatic <check>'
if (insn.opcode == Opcodes.ALOAD && insn.isParameterCheckedForNull()) {
// Go directly to the instruction after 'invokestatic <check>'
insn = insn.next.next.next
continue
}
val varInsn = insn as VarInsnNode
val varIndex = (varInsn).`var`
if (varIndex == expectedArgumentVar) {
// Expected argument variable loaded.
expectedArgumentVar += jvmArgumentTypes[lastArgIndex].size
++lastArgIndex
// Skip a sequence of load instructions referring to the same argument variable
// (such sequence is present in functions like 'Array.copyOf' and can be replaced with DUP instructions).
do {
insn = insn.next
} while (insn != null && insn.opcode == varInsn.opcode && (insn as VarInsnNode).`var` == varIndex)
continue
} else if (varIndex < argumentVarEnd) {
// Loaded an argument variable, but not an expected one => broken evaluation order
return false
} else {
// It's OK to load any non-argument variable during argument evaluation.
insn = insn.next
continue
}
}
// Anything else is fine.
insn = insn.next
}
// Method body is over, but not all arguments were loaded on stack.
if (expectedArgumentVar < argumentVarEnd)
return false
// After arguments evaluation make sure that argument variables are no longer accessed
// (we are not going to store anything to those variables anyway).
while (insn != null) {
if (insn.opcode in Opcodes.ILOAD..Opcodes.ALOAD || insn.opcode in Opcodes.ISTORE..Opcodes.ASTORE) {
if ((insn as VarInsnNode).`var` < argumentVarEnd)
return false
} else if (insn.opcode == Opcodes.IINC) {
if ((insn as IincInsnNode).`var` < argumentVarEnd)
return false
}
insn = insn.next
}
// Didn't encounter anything suspicious.
return true
}
internal data class FieldSignature(
val owner: String,
val name: String,
val desc: String
)
private val whitelistedStaticFields: Set<FieldSignature> =
hashSetOf(
FieldSignature("java/lang/System", "out", "Ljava/io/PrintStream;"),
FieldSignature("kotlin/Result", "Companion", "Lkotlin/Result\$Companion;"),
FieldSignature("kotlin/_Assertions", "ENABLED", "Z")
)
private fun AbstractInsnNode.isProhibitedDuringArgumentsEvaluation() =
opcode in opcodeProhibitedDuringArgumentsEvaluation.indices &&
opcodeProhibitedDuringArgumentsEvaluation[opcode]
private val opcodeProhibitedDuringArgumentsEvaluation = BooleanArray(256).also { a ->
// Any kind of jump during arguments evaluation is a hazard.
// This includes all conditional jump instructions, switch instructions, return and throw instructions.
// Very conservative, but enough for practical cases.
for (i in Opcodes.IFEQ..Opcodes.RETURN) a[i] = true
a[Opcodes.IFNULL] = true
a[Opcodes.IFNONNULL] = true
a[Opcodes.ATHROW] = true
// Instruction with non-trivial side effects is a hazard.
// NB GETSTATIC is taken care of separately.
a[Opcodes.PUTSTATIC] = true
a[Opcodes.PUTFIELD] = true
a[Opcodes.INVOKEVIRTUAL] = true
a[Opcodes.INVOKESPECIAL] = true
a[Opcodes.INVOKESTATIC] = true
a[Opcodes.INVOKEINTERFACE] = true
a[Opcodes.INVOKEDYNAMIC] = true
a[Opcodes.MONITORENTER] = true
a[Opcodes.MONITOREXIT] = true
// Integer division instructions can throw exception
a[Opcodes.IDIV] = true
a[Opcodes.LDIV] = true
a[Opcodes.IREM] = true
a[Opcodes.LREM] = true
// CHECKCAST can throw exception
a[Opcodes.CHECKCAST] = true
// Array creation can throw exception (in case of negative array size)
a[Opcodes.NEWARRAY] = true
a[Opcodes.ANEWARRAY] = true
a[Opcodes.MULTIANEWARRAY] = true
// Array access instructions can throw exception
for (i in Opcodes.IALOAD..Opcodes.SALOAD) a[i] = true
for (i in Opcodes.IASTORE..Opcodes.SASTORE) a[i] = true
}
private const val MARKER_INPLACE_CALL_START = "<INPLACE-CALL-START>"
private const val MARKER_INPLACE_ARGUMENT_START = "<INPLACE-ARGUMENT-START>"
private const val MARKER_INPLACE_ARGUMENT_END = "<INPLACE-ARGUMENT-END>"
private const val MARKER_INPLACE_CALL_END = "<INPLACE-CALL-END>"
private fun InstructionAdapter.addMarker(name: String) {
visitMethodInsn(Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME, name, "()V", false)
}
fun InstructionAdapter.addInplaceCallStartMarker() = addMarker(MARKER_INPLACE_CALL_START)
fun InstructionAdapter.addInplaceCallEndMarker() = addMarker(MARKER_INPLACE_CALL_END)
fun InstructionAdapter.addInplaceArgumentStartMarker() = addMarker(MARKER_INPLACE_ARGUMENT_START)
fun InstructionAdapter.addInplaceArgumentEndMarker() = addMarker(MARKER_INPLACE_ARGUMENT_END)
internal fun AbstractInsnNode.isInplaceCallStartMarker() = isInlineMarker(this, MARKER_INPLACE_CALL_START)
internal fun AbstractInsnNode.isInplaceCallEndMarker() = isInlineMarker(this, MARKER_INPLACE_CALL_END)
internal fun AbstractInsnNode.isInplaceArgumentStartMarker() = isInlineMarker(this, MARKER_INPLACE_ARGUMENT_START)
internal fun AbstractInsnNode.isInplaceArgumentEndMarker() = isInlineMarker(this, MARKER_INPLACE_ARGUMENT_END)

View File

@@ -60,7 +60,7 @@ const val INLINE_FUN_VAR_SUFFIX = "\$iv"
internal const val FIRST_FUN_LABEL = "$$$$\$ROOT$$$$$"
internal const val SPECIAL_TRANSFORMATION_NAME = "\$special"
const val INLINE_TRANSFORMATION_SUFFIX = "\$inlined"
internal const val INLINE_CALL_TRANSFORMATION_SUFFIX = "$" + INLINE_TRANSFORMATION_SUFFIX
internal const val INLINE_CALL_TRANSFORMATION_SUFFIX = "$$INLINE_TRANSFORMATION_SUFFIX"
internal const val INLINE_FUN_THIS_0_SUFFIX = "\$inline_fun"
internal const val DEFAULT_LAMBDA_FAKE_CALL = "$$\$DEFAULT_LAMBDA_FAKE_CALL$$$"
internal const val CAPTURED_FIELD_FOLD_PREFIX = "$$$"
@@ -68,11 +68,10 @@ internal const val CAPTURED_FIELD_FOLD_PREFIX = "$$$"
private const val NON_LOCAL_RETURN = "$$$$\$NON_LOCAL_RETURN$$$$$"
const val CAPTURED_FIELD_PREFIX = "$"
private const val NON_CAPTURED_FIELD_PREFIX = "$$"
private const val INLINE_MARKER_CLASS_NAME = "kotlin/jvm/internal/InlineMarker"
internal const val INLINE_MARKER_CLASS_NAME = "kotlin/jvm/internal/InlineMarker"
private const val INLINE_MARKER_BEFORE_METHOD_NAME = "beforeInlineCall"
private const val INLINE_MARKER_AFTER_METHOD_NAME = "afterInlineCall"
private const val INLINE_MARKER_FINALLY_START = "finallyStart"
private const val INLINE_MARKER_FINALLY_END = "finallyEnd"
private const val INLINE_MARKER_BEFORE_SUSPEND_ID = 0
private const val INLINE_MARKER_AFTER_SUSPEND_ID = 1
@@ -302,7 +301,7 @@ internal fun firstLabelInChain(node: LabelNode): LabelNode {
internal fun areLabelsBeforeSameInsn(first: LabelNode, second: LabelNode): Boolean =
firstLabelInChain(first) == firstLabelInChain(second)
internal val MethodNode?.nodeText: String
val MethodNode?.nodeText: String
get() {
if (this == null) {
return "Not generated"
@@ -535,17 +534,15 @@ internal fun isInlineMarker(insn: AbstractInsnNode): Boolean {
return isInlineMarker(insn, null)
}
private fun isInlineMarker(insn: AbstractInsnNode, name: String?): Boolean {
if (insn !is MethodInsnNode) {
return false
}
internal fun isInlineMarker(insn: AbstractInsnNode, name: String?): Boolean {
if (insn.opcode != Opcodes.INVOKESTATIC) return false
return insn.getOpcode() == Opcodes.INVOKESTATIC &&
insn.owner == INLINE_MARKER_CLASS_NAME &&
val methodInsn = insn as MethodInsnNode
return methodInsn.owner == INLINE_MARKER_CLASS_NAME &&
if (name != null)
insn.name == name
methodInsn.name == name
else
insn.name == INLINE_MARKER_BEFORE_METHOD_NAME || insn.name == INLINE_MARKER_AFTER_METHOD_NAME
methodInsn.name == INLINE_MARKER_BEFORE_METHOD_NAME || methodInsn.name == INLINE_MARKER_AFTER_METHOD_NAME
}
internal fun isBeforeInlineMarker(insn: AbstractInsnNode): Boolean {

View File

@@ -5,13 +5,11 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForCoroutineContext
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForIntercepted
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.codegen.createMethodNodeForAlwaysEnabledAssert
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
@@ -30,25 +28,22 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.MethodNode
fun generateInlineIntrinsicForIr(languageVersionSettings: LanguageVersionSettings, descriptor: FunctionDescriptor): SMAPAndMethodNode? =
fun generateInlineIntrinsicForIr(descriptor: FunctionDescriptor): SMAPAndMethodNode? =
when {
// TODO: implement these as codegen intrinsics (see IrIntrinsicMethods)
descriptor.isBuiltInIntercepted(languageVersionSettings) ->
createMethodNodeForIntercepted(languageVersionSettings)
descriptor.isBuiltInCoroutineContext(languageVersionSettings) ->
createMethodNodeForCoroutineContext(descriptor, languageVersionSettings)
descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSettings)
descriptor.isBuiltInCoroutineContext() ->
createMethodNodeForCoroutineContext(descriptor)
descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn() ->
createMethodNodeForSuspendCoroutineUninterceptedOrReturn()
else -> null
}?.let { SMAPAndMethodNode(it, SMAP(listOf())) }
internal fun generateInlineIntrinsic(
languageVersionSettings: LanguageVersionSettings,
descriptor: FunctionDescriptor,
asmMethod: Method,
typeSystem: TypeSystemCommonBackendContext
): SMAPAndMethodNode? {
return generateInlineIntrinsicForIr(languageVersionSettings, descriptor) ?: when {
return generateInlineIntrinsicForIr(descriptor) ?: when {
isSpecialEnumMethod(descriptor) ->
createSpecialEnumMethodBody(descriptor.name.asString(), descriptor.original.typeParameters.single(), typeSystem)
TypeOfChecker.isTypeOf(descriptor) ->

View File

@@ -19,7 +19,7 @@ import org.jetbrains.org.objectweb.asm.tree.*
object TypeIntrinsics {
@JvmStatic
fun instanceOf(v: InstructionAdapter, jetType: KotlinType, boxedAsmType: Type, isReleaseCoroutines: Boolean) {
fun instanceOf(v: InstructionAdapter, jetType: KotlinType, boxedAsmType: Type) {
val functionTypeArity = getFunctionTypeArity(jetType)
if (functionTypeArity >= 0) {
v.iconst(functionTypeArity)
@@ -27,28 +27,26 @@ object TypeIntrinsics {
return
}
if (isReleaseCoroutines) {
val suspendFunctionTypeArity = getSuspendFunctionTypeArity(jetType)
if (suspendFunctionTypeArity >= 0) {
val notSuspendLambda = Label()
val end = Label()
val suspendFunctionTypeArity = getSuspendFunctionTypeArity(jetType)
if (suspendFunctionTypeArity >= 0) {
val notSuspendLambda = Label()
val end = Label()
with(v) {
dup()
instanceOf(AsmTypes.SUSPEND_FUNCTION_TYPE)
ifeq(notSuspendLambda)
iconst(suspendFunctionTypeArity + 1)
typeIntrinsic(IS_FUNCTON_OF_ARITY_METHOD_NAME, IS_FUNCTON_OF_ARITY_DESCRIPTOR)
goTo(end)
with(v) {
dup()
instanceOf(AsmTypes.SUSPEND_FUNCTION_TYPE)
ifeq(notSuspendLambda)
iconst(suspendFunctionTypeArity + 1)
typeIntrinsic(IS_FUNCTON_OF_ARITY_METHOD_NAME, IS_FUNCTON_OF_ARITY_DESCRIPTOR)
goTo(end)
mark(notSuspendLambda)
pop()
iconst(0)
mark(notSuspendLambda)
pop()
iconst(0)
mark(end)
}
return
mark(end)
}
return
}
val isMutableCollectionMethodName = getIsMutableCollectionMethodName(jetType)

View File

@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.codegen.optimization
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
import org.jetbrains.kotlin.codegen.inline.InplaceArgumentsMethodTransformer
import org.jetbrains.kotlin.codegen.optimization.boxing.PopBackwardPropagationTransformer
import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantBoxingMethodTransformer
import org.jetbrains.kotlin.codegen.optimization.boxing.StackPeepholeOptimizationsTransformer
@@ -40,6 +41,7 @@ class OptimizationMethodVisitor(
UninitializedStoresMethodTransformer(generationState.constructorCallNormalizationMode)
val normalizationMethodTransformer = CompositeMethodTransformer(
InplaceArgumentsMethodTransformer(),
FixStackWithLabelNormalizationMethodTransformer(),
MethodVerifier("AFTER mandatory stack transformations", generationState)
)

View File

@@ -17,9 +17,8 @@
package org.jetbrains.kotlin.codegen.optimization.boxing
import com.google.common.collect.ImmutableSet
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.coroutines.RELEASE_COROUTINES_VERSION_SETTINGS
import org.jetbrains.kotlin.codegen.coroutines.coroutinesJvmInternalPackageFqName
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
@@ -216,7 +215,7 @@ fun AbstractInsnNode.isPrimitiveBoxing() =
}
private val BOXING_CLASS_INTERNAL_NAME =
RELEASE_COROUTINES_VERSION_SETTINGS.coroutinesJvmInternalPackageFqName().child(Name.identifier("Boxing")).topLevelClassInternalName()
StandardNames.COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("Boxing")).topLevelClassInternalName()
private fun isJvmPrimitiveName(name: String) = JvmPrimitiveType.values().any { it.javaKeywordName == name }

View File

@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.codegen.optimization.removeNodeGetNext
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
@@ -36,7 +35,7 @@ val AbstractInsnNode.isMeaningful: Boolean
val AbstractInsnNode.isBranchOrCall: Boolean
get() =
when(this.type) {
when (this.type) {
AbstractInsnNode.JUMP_INSN,
AbstractInsnNode.TABLESWITCH_INSN,
AbstractInsnNode.LOOKUPSWITCH_INSN,
@@ -85,13 +84,17 @@ fun MethodNode.prepareForEmitting() {
current = prev
}
updateMaxStack()
}
fun MethodNode.updateMaxStack() {
maxStack = -1
accept(
MaxStackFrameSizeAndLocalsCalculator(
Opcodes.API_VERSION, access, desc,
object : MethodVisitor(Opcodes.API_VERSION) {
API_VERSION, access, desc,
object : MethodVisitor(API_VERSION) {
override fun visitMaxs(maxStack: Int, maxLocals: Int) {
this@prepareForEmitting.maxStack = maxStack
this@updateMaxStack.maxStack = maxStack
}
})
)
@@ -100,10 +103,10 @@ fun MethodNode.prepareForEmitting() {
fun MethodNode.stripOptimizationMarkers() {
var insn = instructions.first
while (insn != null) {
if (isOptimizationMarker(insn)) {
insn = instructions.removeNodeGetNext(insn)
insn = if (isOptimizationMarker(insn)) {
instructions.removeNodeGetNext(insn)
} else {
insn = insn.next
insn.next
}
}
}
@@ -123,7 +126,7 @@ fun MethodNode.removeUnusedLocalVariables() {
// Arguments are always used whether or not they are in the local variable table
// or used by instructions.
var argumentIndex = 0
val isStatic = (access and Opcodes.ACC_STATIC) != 0
val isStatic = (access and ACC_STATIC) != 0
if (!isStatic) {
used[argumentIndex++] = true
}
@@ -230,8 +233,8 @@ val AbstractInsnNode.intConstant: Int?
fun insnListOf(vararg insns: AbstractInsnNode) = InsnList().apply { insns.forEach { add(it) } }
fun AbstractInsnNode.isStoreOperation(): Boolean = opcode in Opcodes.ISTORE..Opcodes.ASTORE
fun AbstractInsnNode.isLoadOperation(): Boolean = opcode in Opcodes.ILOAD..Opcodes.ALOAD
fun AbstractInsnNode.isStoreOperation(): Boolean = opcode in ISTORE..ASTORE
fun AbstractInsnNode.isLoadOperation(): Boolean = opcode in ILOAD..ALOAD
val AbstractInsnNode?.debugText
get() =

View File

@@ -441,7 +441,7 @@ fun MethodNode.usesLocalExceptParameterNullCheck(index: Int): Boolean =
it is VarInsnNode && it.opcode == Opcodes.ALOAD && it.`var` == index && !it.isParameterCheckedForNull()
}
internal fun AbstractInsnNode.isParameterCheckedForNull(): Boolean =
fun AbstractInsnNode.isParameterCheckedForNull(): Boolean =
next?.takeIf { it.opcode == Opcodes.LDC }?.next?.isCheckParameterIsNotNull() == true
internal fun AbstractInsnNode.isCheckParameterIsNotNull() =

View File

@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.deprecation.CoroutineCompatibilitySupport
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.diagnostics.PrecomputedSuppressCache
@@ -158,8 +157,7 @@ class GenerationState private constructor(
CompilerDeserializationConfiguration(languageVersionSettings)
val deprecationProvider = DeprecationResolver(
LockBasedStorageManager.NO_LOCKS, languageVersionSettings, CoroutineCompatibilitySupport.ENABLED,
JavaDeprecationSettings
LockBasedStorageManager.NO_LOCKS, languageVersionSettings, JavaDeprecationSettings
)
init {

View File

@@ -193,7 +193,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
}
if (descriptor.isSuspendFunctionNotSuspensionView()) {
return mapReturnType(getOrCreateJvmSuspendFunctionView(descriptor as SimpleFunctionDescriptor, isReleaseCoroutines), sw)
return mapReturnType(getOrCreateJvmSuspendFunctionView(descriptor as SimpleFunctionDescriptor), sw)
}
if (hasVoidReturnType(descriptor)) {
@@ -804,7 +804,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
}
if (f.isSuspendFunctionNotSuspensionView()) {
return mapSignature(getOrCreateJvmSuspendFunctionView(f, isReleaseCoroutines), kind, skipGenericSignature)
return mapSignature(getOrCreateJvmSuspendFunctionView(f), kind, skipGenericSignature)
}
if (isDeclarationOfBigArityFunctionInvoke(f) || isDeclarationOfBigArityCreateCoroutineMethod(f)) {

View File

@@ -1,4 +1,3 @@
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.ideaExt.idea
import java.io.File
@@ -10,8 +9,6 @@ plugins {
val compilerModules: Array<String> by rootProject.extra
val otherCompilerModules = compilerModules.filter { it != path }
val tasksWithWarnings: List<String> by rootProject.extra
val antLauncherJar by configurations.creating
dependencies {
@@ -68,18 +65,6 @@ if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
}
}
if (!kotlinBuildProperties.disableWerror) {
allprojects {
tasks.withType<KotlinCompile<*>> {
if (path !in tasksWithWarnings) {
kotlinOptions {
allWarningsAsErrors = true
}
}
}
}
}
projectTest(parallel = true) {
dependsOn(":dist")

View File

@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.ir.backend.js.ic.buildCache
import org.jetbrains.kotlin.ir.backend.js.ic.checkCaches
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
import org.jetbrains.kotlin.js.config.*
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
@@ -205,7 +206,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
cachePath = outputFilePath,
project = projectJs,
mainModule = mainModule,
analyzer = AnalyzerWithCompilerReport(config.configuration),
configuration = config.configuration,
dependencies = libraries,
friendDependencies = friendLibraries,
@@ -219,18 +219,37 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
return OK
}
// Run analysis if main module is sources
lateinit var sourceModule: ModulesStructure
if (arguments.includes == null) {
do {
sourceModule = prepareAnalyzedSourceModule(
projectJs,
environmentForJS.getSourceFiles(),
configurationJs,
libraries,
friendLibraries,
AnalyzerWithCompilerReport(config.configuration),
icUseGlobalSignatures = icCaches.isNotEmpty(),
icUseStdlibCache = icCaches.isNotEmpty(),
icCache = if (icCaches.isNotEmpty()) checkCaches(libraries, icCaches, skipLib = arguments.includes).data else emptyMap()
)
val result = sourceModule.jsFrontEndResult.jsAnalysisResult
if (result is JsAnalysisResult.RetryWithAdditionalRoots) {
environmentForJS.addKotlinSourceRoots(result.additionalKotlinRoots)
}
} while (result is JsAnalysisResult.RetryWithAdditionalRoots)
if (!sourceModule.jsFrontEndResult.jsAnalysisResult.shouldGenerateCode)
return OK
}
if (arguments.irProduceKlibDir || arguments.irProduceKlibFile) {
if (arguments.irProduceKlibFile) {
require(outputFile.extension == KLIB_FILE_EXTENSION) { "Please set up .klib file as output" }
}
generateKLib(
project = config.project,
files = sourcesFiles,
analyzer = AnalyzerWithCompilerReport(config.configuration),
configuration = config.configuration,
dependencies = libraries,
friendDependencies = friendLibraries,
sourceModule,
irFactory = PersistentIrFactory(), // TODO IrFactoryImpl?
outputKlibPath = outputFile.path,
nopack = arguments.irProduceKlibDir,
@@ -246,28 +265,33 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val includes = arguments.includes
val mainModule = if (includes != null) {
val module = if (includes != null) {
if (sourcesFiles.isNotEmpty()) {
messageCollector.report(ERROR, "Source files are not supported when -Xinclude is present")
}
val includesPath = File(includes).canonicalPath
val mainLibPath = libraries.find { File(it).canonicalPath == includesPath }
?: error("No library with name $includes ($includesPath) found")
MainModule.Klib(mainLibPath)
val kLib = MainModule.Klib(mainLibPath)
ModulesStructure(
projectJs,
kLib,
configurationJs,
libraries,
friendLibraries,
icUseGlobalSignatures = icCaches.isNotEmpty(),
icUseStdlibCache = icCaches.isNotEmpty(),
icCache = if (icCaches.isNotEmpty()) checkCaches(libraries, icCaches, skipLib = includes).data else emptyMap()
)
} else {
MainModule.SourceFiles(sourcesFiles)
sourceModule
}
if (arguments.wasm) {
val res = compileWasm(
projectJs,
mainModule,
AnalyzerWithCompilerReport(config.configuration),
config.configuration,
module,
PhaseConfig(wasmPhases),
IrFactoryImpl,
dependencies = libraries,
friendDependencies = friendLibraries,
exportedDeclarations = setOf(FqName("main"))
)
val outputWasmFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "wasm")!!
@@ -278,7 +302,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val runner = """
const wasmBinary = read(String.raw`${outputWasmFile.absoluteFile}`, 'binary');
const wasmModule = new WebAssembly.Module(wasmBinary);
const wasmInstance = new WebAssembly.Instance(wasmModule, { runtime, js_code });
wasmInstance = new WebAssembly.Instance(wasmModule, { runtime, js_code });
wasmInstance.exports.main();
""".trimIndent()
@@ -289,14 +313,9 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val start = System.currentTimeMillis()
val compiledModule = compile(
projectJs,
mainModule,
AnalyzerWithCompilerReport(config.configuration),
config.configuration,
module,
phaseConfig,
if (arguments.irDceDriven) PersistentIrFactory() else IrFactoryImpl,
dependencies = libraries,
friendDependencies = friendLibraries,
mainArguments = mainCallArguments,
generateFullJs = !arguments.irDce,
generateDceJs = arguments.irDce,
@@ -316,8 +335,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
messageCollector
),
lowerPerModule = icCaches.isNotEmpty(),
useStdlibCache = icCaches.isNotEmpty(),
icCache = if (icCaches.isNotEmpty()) checkCaches(libraries, icCaches, skipLib = includes).data else emptyMap(),
)
messageCollector.report(INFO, "Executable production duration: ${System.currentTimeMillis() - start}ms")

View File

@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.load.java.components.JavaDeprecationSettings
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.deprecation.CoroutineCompatibilitySupport
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.KotlinType
@@ -84,7 +83,6 @@ class CliLightClassGenerationSupport(
get() = DeprecationResolver(
LockBasedStorageManager.NO_LOCKS,
languageVersionSettings,
CoroutineCompatibilitySupport.ENABLED,
JavaDeprecationSettings
)

View File

@@ -1,39 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.config
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
fun LanguageVersionSettings.coroutinesPackageFqName(): FqName {
return coroutinesPackageFqName(isReleaseCoroutines())
}
fun LanguageVersionSettings.isReleaseCoroutines() = supportsFeature(LanguageFeature.ReleaseCoroutines)
private fun coroutinesPackageFqName(isReleaseCoroutines: Boolean): FqName {
return if (isReleaseCoroutines)
StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE
else
StandardNames.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL
}
fun LanguageVersionSettings.coroutinesIntrinsicsPackageFqName() =
coroutinesPackageFqName().child(Name.identifier("intrinsics"))
fun LanguageVersionSettings.continuationInterfaceFqName() =
coroutinesPackageFqName().child(Name.identifier("Continuation"))
fun LanguageVersionSettings.restrictsSuspensionFqName() =
coroutinesPackageFqName().child(Name.identifier("RestrictsSuspension"))
fun FqName.isBuiltInCoroutineContext(languageVersionSettings: LanguageVersionSettings) =
if (languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))
this == StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("coroutineContext"))
else
this == StandardNames.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext")) ||
this == StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext"))

View File

@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.daemon.client.experimental
import io.ktor.network.sockets.Socket
import io.ktor.network.sockets.*
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
@@ -438,6 +438,7 @@ class KotlinCompilerClient : KotlinCompilerDaemonClient {
.thenBy(FileAgeComparator()) { it.runFile }
val optsCopy = daemonJVMOptions.copy()
// if required options fit into fattest running daemon - return the daemon and required options with memory params set to actual ones in the daemon
@Suppress("DEPRECATION") // TODO: replace with maxWithOrNull as soon as minimal version of Gradle that we support has Kotlin 1.4+.
aliveWithMetadata.maxWith(comparator)
?.takeIf { daemonJVMOptions memorywiseFitsInto it.jvmOptions }
?.let {

View File

@@ -359,6 +359,7 @@ object KotlinCompilerClient {
.thenBy(FileAgeComparator()) { it.runFile }
val optsCopy = daemonJVMOptions.copy()
// if required options fit into fattest running daemon - return the daemon and required options with memory params set to actual ones in the daemon
@Suppress("DEPRECATION") // TODO: replace with maxWithOrNull as soon as minimal version of Gradle that we support has Kotlin 1.4+.
return aliveWithMetadata.maxWith(comparator)?.takeIf { daemonJVMOptions memorywiseFitsInto it.jvmOptions }?.let {
Pair(it.daemon, optsCopy.updateMemoryUpperBounds(it.jvmOptions))
}

View File

@@ -1,9 +1,9 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:OptIn(ExperimentalPathApi::class)
@file:OptIn(ExperimentalPathApi::class, DelicateCoroutinesApi::class)
package org.jetbrains.kotlin.daemon.experimental.integration

View File

@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.daemon.experimental.unit
import io.ktor.network.sockets.aSocket
import io.ktor.util.*
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
@@ -31,6 +32,7 @@ class TestServer(val serverPort: Int = 6999) {
private val serverSocket = aSocket(selectorMgr).tcp().bind(InetSocketAddress(serverPort))
private val log = Logger.getLogger("TestServer")
@OptIn(DelicateCoroutinesApi::class)
fun awaitClient() = GlobalScope.async {
log.info("accepting clientSocket...")
val client = serverSocket.accept()
@@ -61,7 +63,7 @@ class ClientSerializationTest : KotlinIntegrationTestBase() {
}
}
log.info("printed")
var client2: T? = null
var client2: T?
var connected = false
runBlocking {
val clientAwait = testServer.awaitClient()

View File

@@ -3069,6 +3069,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/equalsAndIdentity.kt");
}
@TestMetadata("incorrectSmartcastToNothing.kt")
public void testIncorrectSmartcastToNothing() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/incorrectSmartcastToNothing.kt");
}
@TestMetadata("kt10240.kt")
public void testKt10240() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/kt10240.kt");

View File

@@ -12,7 +12,7 @@ fun test() {
bar(1, z = true, y = *arrayOf("my", "yours"))
bar(0, z = false, y = "", <!ARGUMENT_PASSED_TWICE!>y<!> = "other")
bar(0, z = false, y = <!ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION_ERROR!>""<!>, <!ARGUMENT_PASSED_TWICE!>y<!> = "other")
bar(0, "", true<!NO_VALUE_FOR_PARAMETER!>)<!>
bar(0, z = false, y = "", <!ARGUMENT_PASSED_TWICE!>y<!> = "other", <!ARGUMENT_PASSED_TWICE!>y<!> = "yet other")
bar(0, z = false, y = <!ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION_ERROR!>""<!>, <!ARGUMENT_PASSED_TWICE!>y<!> = "other", <!ARGUMENT_PASSED_TWICE!>y<!> = "yet other")
}

View File

@@ -7,7 +7,7 @@ FILE: typeAliasWithNotNullBound.kt
}
public final typealias MyAlias = R|Inv<out kotlin/CharSequence>|
public final fun foo(p: R|MyAlias|): R|kotlin/Unit| {
R|/bar|<R|kotlin/CharSequence|>(R|<local>/p|).R|kotlin/CharSequence.length|
R|/bar|<R|CapturedType(out kotlin/CharSequence)|>(R|<local>/p|).R|kotlin/CharSequence.length|
}
public final fun <T : R|kotlin/Any|> bar(x: R|Inv<T>|): R|T| {
^bar R|kotlin/TODO|()

View File

@@ -23,6 +23,16 @@ FILE: const.kt
public get(): R|kotlin/Int|
public final const val l: R|kotlin/Int| = R|/k|
public get(): R|kotlin/Int|
public final const val m: R|kotlin/String| = String(123).R|kotlin/Any.toString|()
public get(): R|kotlin/String|
public final const val n: R|kotlin/Int| = String(456).R|kotlin/String.length|
public get(): R|kotlin/Int|
public final val o: R|kotlin/String| = String(789)
public get(): R|kotlin/String|
public final const val p: R|kotlin/String| = R|/o|.R|kotlin/Any.toString|()
public get(): R|kotlin/String|
public final const val q: R|kotlin/Int| = R|/o|.R|kotlin/String.length|
public get(): R|kotlin/Int|
public final class ForConst : R|kotlin/Any| {
public constructor(): R|ForConst| {
super<R|kotlin/Any|>()

View File

@@ -18,6 +18,11 @@ const val i = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>ForConst.one() + "one"<!>
const val j = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>4 * ForConst.two()<!>
val k = 3 - ForConst.two()
const val l = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>k<!>
const val m = "123".toString()
const val n = "456".length
val o = "789"
const val p = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>o.toString()<!>
const val q = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>o.length<!>
class ForConst{
companion object {

View File

@@ -38,5 +38,5 @@ object F {
}
fun foo() {
const val a = "2"
<!WRONG_MODIFIER_TARGET!>const<!> val a = "2"
}

View File

@@ -8,17 +8,17 @@ fun test() {}
fun test(z: Int, c: Char) {}
<!REDECLARATION!>open class A {
open class <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>A<!> {
open fun rest(s: String) {}
open val u = 20
}<!>
}
<!REDECLARATION!>class A {
class <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>A<!> {
}<!>
}
<!REDECLARATION!>class B : <!FINAL_SUPERTYPE, SUPERTYPE_NOT_INITIALIZED!>A<!> {
class <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>B<!> : <!FINAL_SUPERTYPE, SUPERTYPE_NOT_INITIALIZED!>A<!> {
<!CONFLICTING_OVERLOADS!><!NOTHING_TO_OVERRIDE!>override<!> fun rest(s: String)<!> {}
<!CONFLICTING_OVERLOADS!>fun rest(s: String)<!> {}
@@ -26,17 +26,17 @@ fun test(z: Int, c: Char) {}
fun rest(l: Long) {}
<!NOTHING_TO_OVERRIDE!>override<!> val u = 310
}<!>
}
<!REDECLARATION!>interface B<!>
interface <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>B<!>
<!REDECLARATION!>enum class B<!>
enum class <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>B<!>
<!REDECLARATION!>val u = 10<!>
<!REDECLARATION!>val u = 20<!>
val <!REDECLARATION!>u<!> = 10
val <!REDECLARATION!>u<!> = 20
<!REDECLARATION!>typealias TA = A<!>
<!REDECLARATION!>typealias TA = B<!>
typealias <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>TA<!> = A
typealias <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>TA<!> = B
typealias BA = A
@@ -52,7 +52,7 @@ fun lol(a: Array<Boolean>) {}
class M {
companion <!REDECLARATION!>object<!> {}
<!REDECLARATION!>val Companion = object : Any {}<!>
val <!REDECLARATION!>Companion<!> = object : Any {}
}
fun B.foo() {}

View File

@@ -1,5 +1,5 @@
<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>public<!> class B
<!INCOMPATIBLE_MODIFIERS!>protected<!> <!INCOMPATIBLE_MODIFIERS!>internal<!> class C
<!WRONG_MODIFIER_CONTAINING_DECLARATION!>protected<!> <!INCOMPATIBLE_MODIFIERS!>internal<!> class C
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> class D
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> class E

View File

@@ -6,11 +6,11 @@ infix fun Int.good(x: Int) {}
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun baz(x: Int, y: Int) {}<!>
infix class A
<!WRONG_MODIFIER_TARGET!>infix<!> class A
infix typealias B = A
<!WRONG_MODIFIER_TARGET!>infix<!> typealias B = A
infix val x = 1
<!WRONG_MODIFIER_TARGET!>infix<!> val x = 1
class C {
infix fun good(x: Int) {}

View File

@@ -37,7 +37,7 @@ class F(var a: Int, b: Int, closure: () -> Unit, instance: F?) {
val a = 10
<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>
test(<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>)
<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.<!UNRESOLVED_REFERENCE!>a<!> = 20
<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.a = 20
}, <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>) {
this.a = 30
}

View File

@@ -13,13 +13,13 @@ interface B {
}
interface C {
<!METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE!>override operator fun toString(): String = "Rest"<!>
<!METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE!>override <!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun toString(): String = "Rest"<!>
<!METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE!>override operator fun equals(other: Any?): Boolean = false<!>
<!METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE!>override operator fun hashCode(): Int = 2<!>
<!METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE!>override <!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun hashCode(): Int = 2<!>
}
interface D {
override operator fun toString(): String
override <!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun toString(): String
override operator fun equals(other: Any?): Boolean
override operator fun hashCode(): Int
override <!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun hashCode(): Int
}

View File

@@ -14,7 +14,7 @@ FILE: notASupertype.kt
}
public final fun g(): R|kotlin/Unit| {
this@R|/B|.super<R|kotlin/String|>.<Unresolved name: f>#()
this@R|/B|.super<<ERROR TYPE REF: Not a super type>>.<Unresolved name: f>#()
this@R|/B|.super<R|A|>.R|/A.f|()
}

View File

@@ -4,7 +4,7 @@ open class A {
class B : <!SUPERTYPE_NOT_INITIALIZED!>A<!> {
fun g() {
<!NOT_A_SUPERTYPE!>super<String><!>.<!UNRESOLVED_REFERENCE!>f<!>()
super<<!NOT_A_SUPERTYPE!>String<!>>.f()
super<A>.f()
}
}

View File

@@ -2,7 +2,7 @@
sealed class A
<!REDECLARATION!>class B : A()<!>
class <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>B<!> : A()
interface C : <!INTERFACE_WITH_SUPERCLASS!>A<!>
@@ -30,7 +30,7 @@ sealed class P {
class K : P()
<!REDECLARATION!>object B<!> {
object <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>B<!> {
class I : P()
}

View File

@@ -1,12 +1,12 @@
FILE: superNotAvailable.kt
public final fun R|kotlin/String|.f(): R|kotlin/Unit| {
super<<ERROR TYPE REF: No super type>>@f#.<Unresolved name: compareTo>#(String())
super<<ERROR TYPE REF: No super type>>.<Unresolved name: compareTo>#(String())
<Super not available>#.<Unresolved name: compareTo>#(String())
<Super not available>#.<Unresolved name: compareTo>#(String())
}
public final fun foo(): R|kotlin/Unit| {
super<<ERROR TYPE REF: No super type>>
super<<ERROR TYPE REF: No super type>>.<Unresolved name: foo>#()
super<R|kotlin/Nothing|>.<Unresolved name: foo>#()
<Super not allowed>#
<Super not available>#.<Unresolved name: foo>#()
<Super not available>#.<Unresolved name: foo>#()
}
public final class A : R|kotlin/Any| {
public constructor(): R|A| {

View File

@@ -1,12 +1,12 @@
fun String.f() {
<!SUPER_NOT_AVAILABLE!>super@f<!>.<!UNRESOLVED_REFERENCE!>compareTo<!>("")
<!SUPER_NOT_AVAILABLE!>super<!>.<!UNRESOLVED_REFERENCE!>compareTo<!>("")
<!SUPER_NOT_AVAILABLE!>super@f<!>.compareTo("")
<!SUPER_NOT_AVAILABLE!>super<!>.compareTo("")
}
fun foo() {
<!SUPER_NOT_AVAILABLE!>super<!>
<!SUPER_NOT_AVAILABLE!>super<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
<!SUPER_NOT_AVAILABLE!>super<Nothing><!>.<!UNRESOLVED_REFERENCE!>foo<!>()
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>
<!SUPER_NOT_AVAILABLE!>super<!>.foo()
<!SUPER_NOT_AVAILABLE!>super<Nothing><!>.foo()
}
class A {

View File

@@ -16,7 +16,7 @@ FILE: test.kt
private final val DERIVED_FACTORY: R|DiagnosticFactory0<ft<DerivedElement, DerivedElement?>>| = R|/DiagnosticFactory0.DiagnosticFactory0|<R|ft<DerivedElement, DerivedElement?>|>()
private get(): R|DiagnosticFactory0<ft<DerivedElement, DerivedElement?>>|
public final fun createViaFactory(d: R|EmptyDiagnostic|): R|kotlin/Unit| {
lval casted: R|Diagnostic<ft<DerivedElement, DerivedElement?>>| = R|/DERIVED_FACTORY|.R|SubstitutionOverride</DiagnosticFactory0.cast: R|Diagnostic<ft<DerivedElement, DerivedElement?>>|>|(R|<local>/d|)
lval casted: R|Diagnostic<ft<DerivedElement, DerivedElement?>>| = R|/DERIVED_FACTORY|.R|SubstitutionOverride</DiagnosticFactory0.cast: R|@EnhancedNullability Diagnostic<ft<DerivedElement, DerivedElement?>>|>|(R|<local>/d|)
lval element: R|DerivedElement| = R|<local>/casted|.R|/Diagnostic.element|
R|/Fix.Fix|(R|<local>/element|)
}

View File

@@ -2,7 +2,7 @@
fun x() {}
operator fun Int.invoke(): Foo = <!UNRESOLVED_LABEL!>this@Foo<!>
operator fun Int.invoke(): Foo = this<!UNRESOLVED_LABEL!>@Foo<!>
class Foo {

View File

@@ -1,6 +1,6 @@
<!REDECLARATION!>object A<!>
object <!REDECLARATION!>A<!>
<!REDECLARATION!>val A = 10<!>
val <!REDECLARATION!>A<!> = 10
fun foo() = A

View File

@@ -137,7 +137,7 @@ fun main(args: Array<String?>) {
<!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = args[0]
} else {
a = args.toString()
if (a != null && a.equals("cde")) return
if (<!SENSELESS_COMPARISON!>a != null<!> && a.equals("cde")) return
}
}

View File

@@ -10,7 +10,7 @@ interface Interface {
// Redundant
<!REDUNDANT_MODALITY_MODIFIER!>abstract<!> fun foo()
// error
<!PRIVATE_FUNCTION_WITH_NO_BODY!>private<!> final fun bar()
<!PRIVATE_FUNCTION_WITH_NO_BODY!>private<!> <!WRONG_MODIFIER_CONTAINING_DECLARATION!>final<!> fun bar()
<!REDUNDANT_MODALITY_MODIFIER!>open<!> fun goo() {}
<!REDUNDANT_MODALITY_MODIFIER!>abstract<!> fun tar()
@@ -63,7 +63,7 @@ interface Derived : Interface {
// Redundant
override <!REDUNDANT_MODALITY_MODIFIER!>open<!> fun foo() {}
// error
final class Nested
<!WRONG_MODIFIER_CONTAINING_DECLARATION!>final<!> class Nested
}
// Derived abstract class
abstract class AbstractDerived1(override final val gav: Int) : Interface {
@@ -82,4 +82,4 @@ abstract interface AbstractInterface
// Redundant final object
<!REDUNDANT_MODALITY_MODIFIER!>final<!> object FinalObject
// Open interface
open interface OpenInterface
<!REDUNDANT_MODIFIER_FOR_TARGET!>open<!> interface OpenInterface

View File

@@ -2,15 +2,15 @@
@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class Ann
<!REDECLARATION!>var x: Int
var <!REDECLARATION!>x<!>: Int
get() = 1
set(@Ann private x) { }<!>
set(@Ann <!WRONG_MODIFIER_TARGET!>private<!> x) { }
<!REDECLARATION!>var x: String = ""
var <!REDECLARATION!>x<!>: String = ""
set(param: <!REDUNDANT_SETTER_PARAMETER_TYPE!>String<!>) {
field = "$param "
}<!>
}
class My {
var y: Int = 1
@@ -25,4 +25,4 @@ class My {
set(param) {
field = !param
}
}
}

View File

@@ -1,5 +1,5 @@
fun f() {
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> <!CAN_BE_VAL!>var<!> <!UNUSED_VARIABLE!>baz<!> = 0
<!REDUNDANT_VISIBILITY_MODIFIER, WRONG_MODIFIER_TARGET!>public<!> <!CAN_BE_VAL!>var<!> <!UNUSED_VARIABLE!>baz<!> = 0
class LocalClass {
<!REDUNDANT_VISIBILITY_MODIFIER!>internal<!> var foo = 0
}
@@ -10,11 +10,11 @@ internal <!NOTHING_TO_INLINE!>inline<!> fun internal() {
f()
}
<!REDECLARATION!>class C {
class <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>C<!> {
internal val z = object {
fun foo() = 13
}
}<!>
}
class Foo2<
T1,
@@ -26,12 +26,12 @@ class Foo2<
internal inner class B<T,T2,>
}
<!REDECLARATION!><!REDUNDANT_VISIBILITY_MODIFIER!>public<!> class C {
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> class <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>C<!> {
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> val foo: Int = 0
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> fun bar() {}
}<!>
}
open class D {
protected open fun willRemainProtected() {

View File

@@ -15,7 +15,7 @@ open class B {
override fun foo() {
super.foo()
super.<!UNRESOLVED_REFERENCE!>bar<!>() // should be ambiguity (NB: really we should have overridden bar in C)
<!AMBIGUOUS_SUPER!>super<!>.bar() // should be ambiguity (NB: really we should have overridden bar in C)
super.baz() // Ok
baz() // Ok

View File

@@ -4,5 +4,5 @@ FILE: main.kt
public final fun <D : R|A|> foo(b: R|B<D>|): R|kotlin/Unit| {
}
public final fun main(b: R|B<*>|): R|kotlin/Unit| {
R|/foo|<R|ft<A, A?>|>(R|<local>/b|)
R|/foo|<R|CapturedType(*)|>(R|<local>/b|)
}

View File

@@ -5,7 +5,7 @@ FILE: kt40131.kt
}
public final val <T : R|kotlin/reflect/KClass<*>|> R|T|.myJava1: R|java/lang/Class<*>|
public get(): R|java/lang/Class<*>| {
^ this@R|/myJava1|.R|/javaImpl|<R|kotlin/Any|>
^ this@R|/myJava1|.R|/javaImpl|<R|CapturedType(*)|>
}
public final val <E : R|kotlin/Any|, T : R|kotlin/reflect/KClass<E>|> R|T|.myJava2: R|java/lang/Class<E>|
public get(): R|java/lang/Class<E>| {

View File

@@ -15,19 +15,19 @@ FILE: receiverWithCapturedType.kt
^updateD R|<local>/d|
}
public final fun test_1_1(resolvedCall: R|ResolvedCall<out CallableDescriptor>|): R|kotlin/Unit| {
R|<local>/resolvedCall|.R|/getParameterForArgument|<R|CallableDescriptor|>()
R|<local>/resolvedCall|.R|/getParameterForArgument|<R|CapturedType(out CallableDescriptor)|>()
}
public final fun test_1_2(resolvedCall: R|ResolvedCall<in CallableDescriptor>|): R|kotlin/Unit| {
R|<local>/resolvedCall|.R|/getParameterForArgument|<R|CallableDescriptor|>()
R|<local>/resolvedCall|.R|/getParameterForArgument|<R|CapturedType(in CallableDescriptor)|>()
}
public final fun test_1_3(resolvedCall: R|ResolvedCall<CallableDescriptor>|): R|kotlin/Unit| {
R|<local>/resolvedCall|.R|/getParameterForArgument|<R|CallableDescriptor|>()
}
public final fun test_2_1(resolvedCall: R|ResolvedCall<out CallableDescriptor>|, d: R|CallableDescriptor|): R|kotlin/Unit| {
lval x: R|CallableDescriptor| = R|<local>/resolvedCall|.<Inapplicable(INAPPLICABLE): /updateD>#<R|CallableDescriptor|>(R|<local>/d|)
lval x: R|CallableDescriptor| = R|<local>/resolvedCall|.<Inapplicable(INAPPLICABLE): /updateD>#<R|CapturedType(out CallableDescriptor)|>(R|<local>/d|)
}
public final fun test_2_2(resolvedCall: R|ResolvedCall<in CallableDescriptor>|, d: R|CallableDescriptor|): R|kotlin/Unit| {
lval x: R|CallableDescriptor| = R|<local>/resolvedCall|.R|/updateD|<R|CallableDescriptor|>(R|<local>/d|)
lval x: R|CallableDescriptor| = R|<local>/resolvedCall|.R|/updateD|<R|CapturedType(in CallableDescriptor)|>(R|<local>/d|)
}
public final fun test_2_3(resolvedCall: R|ResolvedCall<CallableDescriptor>|, d: R|CallableDescriptor|): R|kotlin/Unit| {
lval x: R|CallableDescriptor| = R|<local>/resolvedCall|.R|/updateD|<R|CallableDescriptor|>(R|<local>/d|)

View File

@@ -19,10 +19,10 @@ FILE: simpleCapturedTypes.kt
^ this@R|/idP|
}
private final fun getSetterInfos(kc: R|KC<out Ann>|): R|kotlin/Unit| {
R|/id|<R|Ann|>(R|<local>/kc|).R|SubstitutionOverride</KC.x: R|CapturedType(out Ann)|>|.R|/Ann.foo|()
R|<local>/kc|.R|/idR|<R|Ann|>().R|SubstitutionOverride</KC.x: R|CapturedType(out Ann)|>|.R|/Ann.foo|()
R|<local>/kc|.R|/idP|<R|Ann|>.R|SubstitutionOverride</KC.x: R|CapturedType(out Ann)|>|.R|/Ann.foo|()
lval x1: R|KC<out Ann>| = R|/id|<R|Ann|>(R|<local>/kc|)
lval x2: R|KC<out Ann>| = R|<local>/kc|.R|/idR|<R|Ann|>()
lval x3: R|KC<out Ann>| = R|<local>/kc|.R|/idP|<R|Ann|>
R|/id|<R|CapturedType(out Ann)|>(R|<local>/kc|).R|SubstitutionOverride</KC.x: R|CapturedType(out Ann)|>|.R|/Ann.foo|()
R|<local>/kc|.R|/idR|<R|CapturedType(out Ann)|>().R|SubstitutionOverride</KC.x: R|CapturedType(out Ann)|>|.R|/Ann.foo|()
R|<local>/kc|.R|/idP|<R|CapturedType(out Ann)|>.R|SubstitutionOverride</KC.x: R|CapturedType(out Ann)|>|.R|/Ann.foo|()
lval x1: R|KC<out Ann>| = R|/id|<R|CapturedType(out Ann)|>(R|<local>/kc|)
lval x2: R|KC<out Ann>| = R|<local>/kc|.R|/idR|<R|CapturedType(out Ann)|>()
lval x3: R|KC<out Ann>| = R|<local>/kc|.R|/idP|<R|CapturedType(out Ann)|>
}

View File

@@ -1,7 +1,7 @@
class A {
<!INLINE_CLASS_NOT_TOP_LEVEL!>inline<!> inner class B(val x: Int)
fun foo() {
<!INLINE_CLASS_NOT_TOP_LEVEL!>inline<!> class C(val x: Int)
<!INLINE_CLASS_NOT_TOP_LEVEL, WRONG_MODIFIER_TARGET!>inline<!> class C(val x: Int)
}
inner <!INLINE_CLASS_NOT_TOP_LEVEL!>value<!> class D(val x: Int)
}

View File

@@ -40,8 +40,8 @@ FILE: referenceToExtension.kt
}
public final fun test_2(): R|kotlin/Unit| {
lval extensionValRef: R|kotlin/reflect/KProperty1<GenericTest.B<*>, GenericTest.A<CapturedType(*)>>| = Q|GenericTest.B|::R|/GenericTest.extensionVal<kotlin/Any?>|
lval extensionFunRef: R|@ExtensionFunctionType kotlin/reflect/KFunction1<GenericTest.B<*>, GenericTest.A<CapturedType(*)>>| = Q|GenericTest.B|::R|/GenericTest.extensionFun<kotlin/Any?>|
lval extensionValRef: R|kotlin/reflect/KProperty1<GenericTest.B<*>, GenericTest.A<CapturedType(*)>>| = Q|GenericTest.B|::R|/GenericTest.extensionVal<CapturedType(*)>|
lval extensionFunRef: R|@ExtensionFunctionType kotlin/reflect/KFunction1<GenericTest.B<*>, GenericTest.A<CapturedType(*)>>| = Q|GenericTest.B|::R|/GenericTest.extensionFun<CapturedType(*)>|
}
}

View File

@@ -702,44 +702,45 @@ digraph boundSmartcastsInBranches_kt {
293 [label="Access variable R|<local>/x|"];
294 [label="Access variable <Inapplicable(UNSAFE_CALL): kotlin/String.length>#"];
295 [label="Access variable R|<local>/y|"];
296 [label="Access variable R|kotlin/String.length|"];
297 [label="Access variable R|<local>/z|"];
298 [label="Access variable <Inapplicable(UNSAFE_CALL): kotlin/String.length>#"];
299 [label="Exit block"];
296 [label="Stub" style="filled" fillcolor=gray];
297 [label="Access variable R|kotlin/String.length|" style="filled" fillcolor=gray];
298 [label="Access variable R|<local>/z|" style="filled" fillcolor=gray];
299 [label="Access variable <Inapplicable(UNSAFE_CALL): kotlin/String.length>#" style="filled" fillcolor=gray];
300 [label="Exit block" style="filled" fillcolor=gray];
}
300 [label="Exit when branch result"];
301 [label="Exit when"];
301 [label="Exit when branch result" style="filled" fillcolor=gray];
302 [label="Exit when"];
}
subgraph cluster_67 {
color=blue
302 [label="Enter when"];
303 [label="Enter when"];
subgraph cluster_68 {
color=blue
303 [label="Enter when branch condition "];
304 [label="Access variable R|<local>/z|"];
305 [label="Const: Null(null)"];
306 [label="Equality operator !="];
307 [label="Exit when branch condition"];
304 [label="Enter when branch condition "];
305 [label="Access variable R|<local>/z|"];
306 [label="Const: Null(null)"];
307 [label="Equality operator !="];
308 [label="Exit when branch condition"];
}
308 [label="Synthetic else branch"];
309 [label="Enter when branch result"];
309 [label="Synthetic else branch"];
310 [label="Enter when branch result"];
subgraph cluster_69 {
color=blue
310 [label="Enter block"];
311 [label="Access variable R|<local>/x|"];
312 [label="Access variable R|kotlin/String.length|"];
313 [label="Access variable R|<local>/y|"];
314 [label="Access variable <Inapplicable(UNSAFE_CALL): kotlin/String.length>#"];
315 [label="Access variable R|<local>/z|"];
316 [label="Access variable R|kotlin/String.length|"];
317 [label="Exit block"];
311 [label="Enter block"];
312 [label="Access variable R|<local>/x|"];
313 [label="Access variable R|kotlin/String.length|"];
314 [label="Access variable R|<local>/y|"];
315 [label="Access variable <Inapplicable(UNSAFE_CALL): kotlin/String.length>#"];
316 [label="Access variable R|<local>/z|"];
317 [label="Access variable R|kotlin/String.length|"];
318 [label="Exit block"];
}
318 [label="Exit when branch result"];
319 [label="Exit when"];
319 [label="Exit when branch result"];
320 [label="Exit when"];
}
320 [label="Exit block"];
321 [label="Exit block"];
}
321 [label="Exit function test_7" style="filled" fillcolor=red];
322 [label="Exit function test_7" style="filled" fillcolor=red];
}
202 -> {203};
203 -> {204};
@@ -829,26 +830,27 @@ digraph boundSmartcastsInBranches_kt {
287 -> {288};
288 -> {289};
289 -> {291 290};
290 -> {301};
290 -> {302};
291 -> {292};
292 -> {293};
293 -> {294};
294 -> {295};
295 -> {296};
296 -> {297};
297 -> {298};
298 -> {299};
299 -> {300};
300 -> {301};
301 -> {302};
295 -> {322} [label=onUncaughtException];
295 -> {296} [style=dotted];
296 -> {297} [style=dotted];
297 -> {298} [style=dotted];
298 -> {299} [style=dotted];
299 -> {300} [style=dotted];
300 -> {301} [style=dotted];
301 -> {302} [style=dotted];
302 -> {303};
303 -> {304};
304 -> {305};
305 -> {306};
306 -> {307};
307 -> {309 308};
308 -> {319};
309 -> {310};
307 -> {308};
308 -> {310 309};
309 -> {320};
310 -> {311};
311 -> {312};
312 -> {313};
@@ -860,5 +862,6 @@ digraph boundSmartcastsInBranches_kt {
318 -> {319};
319 -> {320};
320 -> {321};
321 -> {322};
}

View File

@@ -107,7 +107,7 @@ fun test_7() {
y<!UNSAFE_CALL!>.<!>length // Bad
z.length // OK
}
if (y != null) {
if (<!SENSELESS_COMPARISON!>y != null<!>) {
x<!UNSAFE_CALL!>.<!>length // Bad
y.length // OK
z<!UNSAFE_CALL!>.<!>length // Bad

View File

@@ -0,0 +1,144 @@
digraph incorrectSmartcastToNothing_kt {
graph [nodesep=3]
node [shape=box penwidth=2]
edge [penwidth=2]
subgraph cluster_0 {
color=red
0 [label="Enter property" style="filled" fillcolor=red];
1 [label="Const: String(foo)"];
2 [label="Function call: R|java/io/File.File|(...)"];
3 [label="Exit property" style="filled" fillcolor=red];
}
0 -> {1};
1 -> {2};
2 -> {3};
subgraph cluster_1 {
color=red
4 [label="Enter function test" style="filled" fillcolor=red];
subgraph cluster_2 {
color=blue
5 [label="Enter block"];
subgraph cluster_3 {
color=blue
6 [label="Enter when"];
subgraph cluster_4 {
color=blue
7 [label="Enter when branch condition "];
8 [label="Access variable R|<local>/cacheExtSetting|"];
9 [label="Const: Null(null)"];
10 [label="Equality operator =="];
11 [label="Exit when branch condition"];
}
subgraph cluster_5 {
color=blue
12 [label="Enter when branch condition "];
13 [label="Access variable R|<local>/cacheExtSetting|"];
14 [label="Function call: R|<local>/cacheExtSetting|.R|kotlin/text/isBlank|()"];
15 [label="Exit when branch condition"];
}
subgraph cluster_6 {
color=blue
16 [label="Enter when branch condition else"];
17 [label="Exit when branch condition"];
}
18 [label="Enter when branch result"];
subgraph cluster_7 {
color=blue
19 [label="Enter block"];
20 [label="Access variable R|<local>/cacheExtSetting|"];
21 [label="Function call: R|java/io/File.File|(...)"];
22 [label="Exit block"];
}
23 [label="Exit when branch result"];
24 [label="Enter when branch result"];
subgraph cluster_8 {
color=blue
25 [label="Enter block"];
26 [label="Const: Null(null)"];
27 [label="Exit block"];
}
28 [label="Exit when branch result"];
29 [label="Enter when branch result"];
subgraph cluster_9 {
color=blue
30 [label="Enter block"];
31 [label="Access variable R|/cache|"];
32 [label="Enter safe call"];
33 [label="Postponed enter to lambda"];
subgraph cluster_10 {
color=blue
43 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_11 {
color=blue
44 [label="Enter block"];
45 [label="Access variable R|<local>/it|"];
46 [label="Const: String(main.kts.compiled.cache)"];
47 [label="Function call: R|java/io/File.File|(...)"];
48 [label="Exit block"];
}
49 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
34 [label="Postponed exit from lambda"];
35 [label="Function call: $subj$.R|kotlin/let|<R|java/io/File|, R|java/io/File|>(...)"];
36 [label="Exit safe call"];
37 [label="Exit block"];
}
38 [label="Exit when branch result"];
39 [label="Exit when"];
}
40 [label="Variable declaration: lval cacheBaseDir: R|java/io/File?|"];
41 [label="Exit block"];
}
42 [label="Exit function test" style="filled" fillcolor=red];
}
4 -> {5};
5 -> {6};
6 -> {7};
7 -> {8};
8 -> {9};
9 -> {10};
10 -> {11};
11 -> {29 12};
12 -> {13};
13 -> {14};
14 -> {15};
15 -> {24 16};
16 -> {17};
17 -> {18};
18 -> {19};
19 -> {20};
20 -> {21};
21 -> {22};
22 -> {23};
23 -> {39};
24 -> {25};
25 -> {26};
26 -> {27};
27 -> {28};
28 -> {39};
29 -> {30};
30 -> {31};
31 -> {32 36};
32 -> {33};
33 -> {43};
33 -> {34} [color=red];
33 -> {43} [style=dashed];
34 -> {35};
35 -> {36};
36 -> {37};
37 -> {38};
38 -> {39};
39 -> {40};
40 -> {41};
41 -> {42};
43 -> {44};
44 -> {45};
45 -> {46};
46 -> {47};
47 -> {48};
48 -> {49};
49 -> {34} [color=green];
}

View File

@@ -0,0 +1,20 @@
FILE: incorrectSmartcastToNothing.kt
public final val cache: R|java/io/File?| = R|java/io/File.File|(String(foo))
public get(): R|java/io/File?|
public final fun test(cacheExtSetting: R|kotlin/String?|): R|kotlin/Unit| {
lval cacheBaseDir: R|java/io/File?| = when () {
==(R|<local>/cacheExtSetting|, Null(null)) -> {
R|/cache|?.{ $subj$.R|kotlin/let|<R|java/io/File|, R|java/io/File|>(<L> = let@fun <anonymous>(it: R|java/io/File|): R|java/io/File| <inline=Inline, kind=EXACTLY_ONCE> {
^ R|java/io/File.File|(R|<local>/it|, String(main.kts.compiled.cache))
}
) }
}
R|<local>/cacheExtSetting|.R|kotlin/text/isBlank|() -> {
Null(null)
}
else -> {
R|java/io/File.File|(R|<local>/cacheExtSetting|)
}
}
}

View File

@@ -0,0 +1,15 @@
// WITH_STDLIB
// FULL_JDK
// DUMP_CFG
import java.io.File
val cache: File? = File("foo")
fun test(cacheExtSetting: String?) {
val cacheBaseDir = when {
cacheExtSetting == null -> cache?.let { File(it, "main.kts.compiled.cache") }
cacheExtSetting.isBlank() -> null
else -> File(cacheExtSetting)
}
}

View File

@@ -14,7 +14,7 @@ var Any?.isNotNull: Boolean
set(value) {
contract {
returns() implies (this@isNotNull != null)
<!ERROR_IN_CONTRACT_DESCRIPTION!>require(this != null)<!>
<!ERROR_IN_CONTRACT_DESCRIPTION!>require(<!SENSELESS_COMPARISON!>this != null<!>)<!>
}
}

View File

@@ -25,7 +25,7 @@ abstract class NotRange4() {
}
abstract class ImproperIterator3 {
abstract operator fun hasNext() : Int
abstract <!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun hasNext() : Int
abstract operator fun next() : Int
}

View File

@@ -0,0 +1,28 @@
FILE: EnumWithToString.kt
public final enum class Some : R|kotlin/Enum<Some>| {
private constructor(): R|Some| {
super<R|kotlin/Enum<Some>|>()
}
public final static enum entry ENTRY: R|Some| = object : R|Some| {
private constructor(): R|<anonymous>| {
super<R|Some|>()
}
public final override fun toString(): R|kotlin/String| {
^toString String(Entry)
}
}
public open override fun toString(): R|kotlin/String| {
^toString String(Some)
}
public final static fun values(): R|kotlin/Array<Some>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|Some| {
}
}

View File

@@ -0,0 +1,7 @@
enum class Some {
ENTRY {
override fun toString(): String = "Entry"
};
override fun toString(): String = "Some"
}

View File

@@ -0,0 +1,9 @@
FILE: IntersectionWithJavaString.kt
public final fun collapse(path: R|kotlin/String|): R|kotlin/Unit| {
lval result: R|ft<kotlin/String, kotlin/String?>| = (R|<local>/path| as R|java/lang/String|).R|java/lang/String.replace|(String(123), String(456))
when () {
!==(R|<local>/result|, R|<local>/path|) -> {
}
}
}

View File

@@ -0,0 +1,5 @@
// FULL_JDK
fun collapse(path: String) {
val result = (path as java.lang.String).replace("123", "456")
if (<!EQUALITY_NOT_APPLICABLE_WARNING!>result !== path<!>) {}
}

View File

@@ -0,0 +1,19 @@
FILE: use.kt
public final class BeforeRunTask<T> : R|kotlin/Any| {
public constructor<T>(): R|BeforeRunTask<T>| {
super<R|kotlin/Any|>()
}
}
public abstract interface PersistentStateComponent<T> : R|kotlin/Any| {
}
public final fun <T> deserializeAndLoadState(component: R|PersistentStateComponent<T>|, clazz: R|java/lang/Class<T>| = Q|ComponentSerializationUtil|.R|/ComponentSerializationUtil.getStateClass|<R|ft<T!!, T?>|>(<getClass>(R|<local>/component|).R|kotlin/jvm/java|<R|CapturedType(out PersistentStateComponent<T>)|>)): R|kotlin/Unit| {
}
public final fun use(beforeRunTask: R|BeforeRunTask<*>|): R|kotlin/Unit| {
when () {
(R|<local>/beforeRunTask| is R|PersistentStateComponent<*>|) -> {
R|/deserializeAndLoadState|<R|CapturedType(*)|>(R|<local>/beforeRunTask|)
}
}
}

View File

@@ -0,0 +1,27 @@
// FILE: ComponentSerializationUtil.java
import org.jetbrains.annotations.NotNull;
public final class ComponentSerializationUtil {
@NotNull
public static <S> Class<S> getStateClass(@NotNull Class<? extends PersistentStateComponent> aClass)
{}
}
// FILE: use.kt
class BeforeRunTask<T>
interface PersistentStateComponent<T>
fun <T> deserializeAndLoadState(
component: PersistentStateComponent<T>,
clazz: Class<T> = ComponentSerializationUtil.getStateClass(component::class.java)
) {}
fun use(beforeRunTask: BeforeRunTask<*>) {
if (beforeRunTask is PersistentStateComponent<*>) {
deserializeAndLoadState(beforeRunTask)
}
}

View File

@@ -0,0 +1,42 @@
FILE: UastPatterns.kt
public abstract interface UElement : R|kotlin/Any| {
}
public abstract interface UExpression : R|UElement| {
}
public abstract interface UReferenceExpression : R|UExpression| {
}
public final fun injectionHostOrReferenceExpression(): R|UExpressionPattern.Capture<UExpression>| {
^injectionHostOrReferenceExpression R|/uExpression|().R|SubstitutionOverride</UExpressionPattern.Capture.filter: R|UExpressionPattern.Capture<UExpression>|>|(<L> = filter@fun <anonymous>(it: R|UExpression|): R|kotlin/Boolean| <inline=NoInline> {
^ (R|<local>/it| is R|UReferenceExpression|)
}
)
}
public final fun uExpression(): R|UExpressionPattern.Capture<UExpression>| {
^uExpression R|/expressionCapture|<R|UExpression|>(<getClass>(Q|UExpression|).R|kotlin/jvm/java|<R|UExpression|>)
}
public final fun <T : R|UExpression|> expressionCapture(clazz: R|java/lang/Class<T>|): R|UExpressionPattern.Capture<T>| {
^expressionCapture Q|UExpressionPattern|.R|SubstitutionOverride</UExpressionPattern.Capture.Capture>|<R|T|>(R|<local>/clazz|)
}
public open class UElementPattern<T : R|UElement|, Self : R|UElementPattern<T, Self>|> : R|ObjectPattern<T, Self>| {
public constructor<T : R|UElement|, Self : R|UElementPattern<T, Self>|>(clazz: R|java/lang/Class<T>|): R|UElementPattern<T, Self>| {
super<R|ObjectPattern<T, Self>|>(R|<local>/clazz|)
}
public final fun filter(filter: R|(T) -> kotlin/Boolean|): R|Self| {
^filter (this@R|/UElementPattern| as R|Self|)
}
}
public open class UExpressionPattern<T : R|UExpression|, Self : R|UExpressionPattern<T, Self>|> : R|UElementPattern<T, Self>| {
public constructor<T : R|UExpression|, Self : R|UExpressionPattern<T, Self>|>(clazz: R|java/lang/Class<T>|): R|UExpressionPattern<T, Self>| {
super<R|UElementPattern<T, Self>|>(R|<local>/clazz|)
}
public open class Capture<T : R|UExpression|> : R|UExpressionPattern<T, UExpressionPattern.Capture<T>>| {
public constructor<T : R|UExpression|>(clazz: R|java/lang/Class<T>|): R|UExpressionPattern.Capture<T>| {
super<R|UExpressionPattern<T, UExpressionPattern.Capture<T>>|>(R|<local>/clazz|)
}
}
}

View File

@@ -0,0 +1,38 @@
// FILE: ObjectPattern.java
import org.jetbrains.annotations.NotNull;
public abstract class ObjectPattern<T, Self extends ObjectPattern<T, Self>> {
protected ObjectPattern(@NotNull Class<T> aClass) {
}
public static class Capture<T> extends ObjectPattern<T,Capture<T>> {
public Capture(@NotNull Class<T> aClass) {
super(aClass);
}
}
}
// FILE: UastPatterns.kt
interface UElement
interface UExpression : UElement
interface UReferenceExpression : UExpression
fun injectionHostOrReferenceExpression(): UExpressionPattern.Capture<UExpression> =
uExpression().filter { it is UReferenceExpression }
fun uExpression(): UExpressionPattern.Capture<UExpression> = expressionCapture(UExpression::class.java)
fun <T : UExpression> expressionCapture(clazz: Class<T>): UExpressionPattern.Capture<T> = UExpressionPattern.Capture(clazz)
open class UElementPattern<T : UElement, Self : UElementPattern<T, Self>>(clazz: Class<T>) : ObjectPattern<T, Self>(clazz) {
fun filter(filter: (T) -> Boolean): Self = this as Self
}
open class UExpressionPattern<T : UExpression, Self : UExpressionPattern<T, Self>>(clazz: Class<T>) : UElementPattern<T, Self>(clazz) {
open class Capture<T : UExpression>(clazz: Class<T>) : UExpressionPattern<T, Capture<T>>(clazz)
}

View File

@@ -0,0 +1,24 @@
FILE: WithSpeedSearch.kt
public final class JList<E> : R|kotlin/Any| {
public constructor<E>(): R|JList<E>| {
super<R|kotlin/Any|>()
}
}
public final class ListSpeedSearch<T> : R|kotlin/Any| {
public constructor<T>(list: R|JList<T>|): R|ListSpeedSearch<T>| {
super<R|kotlin/Any|>()
}
}
public final class XThreadsFramesView : R|kotlin/Any| {
public constructor(): R|XThreadsFramesView| {
super<R|kotlin/Any|>()
}
private final fun <J : R|JList<*>|> R|J|.withSpeedSearch(): R|J| {
lval search: R|ListSpeedSearch<out kotlin/Any?>| = R|/ListSpeedSearch.ListSpeedSearch|<R|CapturedType(*)|>(this@R|/XThreadsFramesView.withSpeedSearch|)
^withSpeedSearch this@R|/XThreadsFramesView.withSpeedSearch|
}
}

View File

@@ -0,0 +1,10 @@
class JList<E>
class ListSpeedSearch<T>(list: JList<T>)
class XThreadsFramesView {
private fun <J> J.withSpeedSearch(): J where J : JList<*> {
val search = ListSpeedSearch(this)
return this
}
}

View File

@@ -7,7 +7,7 @@ FILE: test.kt
super<R|kotlin/Any|>()
}
private final val klass: R|java/lang/Class<out MyTest>| = <getClass>(this@R|/MyTest|).R|kotlin/jvm/java|<R|MyTest|>
private final val klass: R|java/lang/Class<out MyTest>| = <getClass>(this@R|/MyTest|).R|kotlin/jvm/java|<R|CapturedType(out MyTest)|>
private get(): R|java/lang/Class<out MyTest>|
private final val logger: R|ft<Logger, Logger?>| = Q|Logger|.R|/Logger.getInstance|(this@R|/MyTest|.R|/MyTest.klass|)

View File

@@ -1,4 +1,4 @@
FILE: capturedFlexible.kt
public final fun foo(z: R|java/util/zip/ZipFile|): R|kotlin/Unit| {
R|<local>/z|.R|java/util/zip/ZipFile.entries|().R|kotlin/sequences/asSequence|<R|ft<java/util/zip/ZipEntry, java/util/zip/ZipEntry?>|>()
R|<local>/z|.R|java/util/zip/ZipFile.entries|().R|kotlin/sequences/asSequence|<R|CapturedType(out ft<java/util/zip/ZipEntry, java/util/zip/ZipEntry?>)|>()
}

View File

@@ -13,7 +13,7 @@ fun test() {
val Any.bar get() = "456"
val String.bar get() = "987"
<!REDECLARATION!>val t = "".bar<!>
val <!REDECLARATION!>t<!> = "".bar
val p = Pair(0, "")
@@ -21,4 +21,4 @@ open class Base<T>(val x: T)
class Derived : Base<Int>(10)
val xx = Derived().x + 1
<!REDECLARATION!>val t = throw AssertionError("")<!>
val <!REDECLARATION!>t<!> = throw AssertionError("")

View File

@@ -3467,6 +3467,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/equalsAndIdentity.kt");
}
@Test
@TestMetadata("incorrectSmartcastToNothing.kt")
public void testIncorrectSmartcastToNothing() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/incorrectSmartcastToNothing.kt");
}
@Test
@TestMetadata("kt10240.kt")
public void testKt10240() throws Exception {
@@ -5032,6 +5038,36 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
public void testDailyAggregatedDoubleFactor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/DailyAggregatedDoubleFactor.kt");
}
@Test
@TestMetadata("EnumWithToString.kt")
public void testEnumWithToString() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/EnumWithToString.kt");
}
@Test
@TestMetadata("IntersectionWithJavaString.kt")
public void testIntersectionWithJavaString() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/IntersectionWithJavaString.kt");
}
@Test
@TestMetadata("PersistentStateComponent.kt")
public void testPersistentStateComponent() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/PersistentStateComponent.kt");
}
@Test
@TestMetadata("UastPatterns.kt")
public void testUastPatterns() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/UastPatterns.kt");
}
@Test
@TestMetadata("WithSpeedSearch.kt")
public void testWithSpeedSearch() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/WithSpeedSearch.kt");
}
}
@Nested

View File

@@ -3467,6 +3467,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/equalsAndIdentity.kt");
}
@Test
@TestMetadata("incorrectSmartcastToNothing.kt")
public void testIncorrectSmartcastToNothing() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/incorrectSmartcastToNothing.kt");
}
@Test
@TestMetadata("kt10240.kt")
public void testKt10240() throws Exception {
@@ -5032,6 +5038,36 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
public void testDailyAggregatedDoubleFactor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/DailyAggregatedDoubleFactor.kt");
}
@Test
@TestMetadata("EnumWithToString.kt")
public void testEnumWithToString() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/EnumWithToString.kt");
}
@Test
@TestMetadata("IntersectionWithJavaString.kt")
public void testIntersectionWithJavaString() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/IntersectionWithJavaString.kt");
}
@Test
@TestMetadata("PersistentStateComponent.kt")
public void testPersistentStateComponent() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/PersistentStateComponent.kt");
}
@Test
@TestMetadata("UastPatterns.kt")
public void testUastPatterns() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/UastPatterns.kt");
}
@Test
@TestMetadata("WithSpeedSearch.kt")
public void testWithSpeedSearch() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/WithSpeedSearch.kt");
}
}
@Nested

Some files were not shown because too many files have changed in this diff Show More