Compare commits

...

1199 Commits

Author SHA1 Message Date
Dmitry Petrov
8b33a50783 JVM skip methods without NEW insns in UninitializedStoresProcessor 2021-07-22 08:23:38 +03:00
Dmitry Petrov
cf7d0a1566 Minor HackedFixStackMethodAnalyzerBase -> FastStackAnalyzer 2021-07-21 16:19:02 +03:00
Dmitry Petrov
8b46dce8a2 JVM use new stack state analyzer in non-local returns preprocessing 2021-07-21 15:28:50 +03:00
Dmitry Petrov
5785e29e32 JVM don't use SPBs in FixStack method analyzer (we don't merge) 2021-07-21 15:28:50 +03:00
Dmitry Petrov
2376033218 JVM don't optimize if there are too many data on exception edges 2021-07-21 15:28:49 +03:00
Dmitry Petrov
ddd1a0a376 JVM skip redundant boxing optimization in methods without boxing 2021-07-21 15:28:49 +03:00
Leonid Startsev
3d0126d5dd Revert "Instantiation of annotations for JVM IR with the corresponding feature flag"
because of incorrect rebase

This reverts commit ce0a3a57
2021-07-21 15:23:24 +03:00
max-kammerer
5b21444805 Update worker11.kt 2021-07-21 13:36:02 +02:00
Leonid Startsev
ce0a3a57df Instantiation of annotations for JVM IR with the corresponding feature flag
Seperate checker for platforms that do not support this language feature yet

Synthetic implementations of annotations are generated on-demand with proper 
equals, hashCode, and annotationType methods

#KT-47699 Fixed
2021-07-21 10:23:51 +00:00
Leonid Startsev
4bc521249b kotlinx.serialization: Support InheritableSerialInfo 2021-07-21 10:06:12 +00:00
Alexander Dudinsky
8eea749231 Accept android licenses in setUp PureAndroidAndJavaConsumeMppLibIT 2021-07-21 12:33:07 +03:00
Nikolay Krasko
a1a1bda5f3 Drop unused runIdeTask and excludeInAndroidStudio from localDependencies 2021-07-21 11:23:56 +02:00
Nikolay Krasko
6a0b71d3e4 Drop old IDEA run configurations 2021-07-21 11:23:56 +02:00
Nikita Bobko
d1e46e8ce7 Delete Kotlin IntelliJ IDEA plugin modules from settings.gradle 2021-07-21 11:23:53 +02:00
Nikita Bobko
39fa2b0baf Delete Kotlin IntelliJ IDEA plugin sources
Kotlin plugin sources were migrated to intellij-community:
https://github.com/JetBrains/intellij-community/tree/master/plugins/kotlin

Preserve `jps-plugin/testData/incremental`
because it's used in `compiler/incremental-compilation-impl/test`

Preserve `idea/testData/multiModuleHighlighting/multiplatform`
because it's used in `MppHighlightingTestDataWithGradleIT`
2021-07-21 11:23:43 +02:00
Elena Lepilkina
b8d74698f1 [K/N][Docs] Update HACKING.md after repositories merging and adding information about debugging and using CLion 2021-07-21 08:39:10 +00:00
Mads Ager
6436a1686d [JVM_IR] Recursively perform constant lowering.
Otherwise constants in child expressions are not transformed.

^KT-47716 Fixed.
2021-07-21 02:11:41 +02:00
Mads Ager
2877f1cabe [JVM_IR] Fix check for inline class property backing in lowering.
The inline class lowering would attempt to lower a companion object
property backing field.

^KT-47762 Fixed.
2021-07-21 01:56:46 +02:00
Dmitry Petrov
46d2e52543 JVM Minor: move uninitialized value check to stack recovery 2021-07-20 19:51:04 +03:00
Dmitry Petrov
e72d24960d JVM we don't merge frames in stack normalization 2021-07-20 19:51:03 +03:00
Dmitry Petrov
91afa3335c JVM represent uninitialized values explicitly in stack normalization 2021-07-20 19:51:02 +03:00
Dmitry Petrov
bb202318ee Minor: regenerate tests 2021-07-20 19:51:01 +03:00
Dmitry Petrov
35b4a9d4cc JVM treat all variable loads as "initialized" in stack normalization 2021-07-20 19:51:00 +03:00
Dmitry Petrov
c8b705fd2d JVM update license for HackedFixStackMethodAnalyzerBase.kt 2021-07-20 19:50:59 +03:00
Dmitry Petrov
8763235053 JVM specially hacked method analyzer for FixStack 2021-07-20 19:50:58 +03:00
Dmitry Petrov
3ecd612ce7 JVM FixStackValue & FixStackInterpreter 2021-07-20 19:50:57 +03:00
Ilya Chernikov
8eb7e719d3 [minor] fix compiler warnings in scripting modules 2021-07-20 19:42:34 +03:00
Roman Golyshev
59304ba70c FIR IDE: use correct out of block modification tracker
Follow-up to eead868cd2
2021-07-20 19:15:38 +03:00
Roman Golyshev
4e67afcaba FIR IDE: Use write lock in KtFirOverrideInfoProvider implementation
`withFir` takes read lock, but checking visibility or implementation
status actually requires resolving declaration to `STATUS` phase. But
resolve cannot be done in `withFir` function, since resolve requires
write lock, and you cannot take both read and write lock

Now we use `withFirWithPossibleResolveInside`, which takes write lock
and allows to perform resolve in it

This should fix failing `FirOverrideImplementTest` tests
in Kotlin IDE plugin
2021-07-20 19:02:26 +03:00
Roman Golyshev
f3bdadb7d9 FIR IDE: Use correct class symbol in getImplementationStatus
The previous check `if (parentClassSymbol !is FirClassSymbol<*>)`
always succeeded, because `parentClassSymbol` was a declaration,
not a symbol
2021-07-20 19:02:24 +03:00
Abduqodiri Qurbonzoda
b65c477e68 Regex.splitToSequence, CharSequence.splitToSequence(Regex) #KT-23351 2021-07-20 14:09:24 +00:00
Abduqodiri Qurbonzoda
1fee6b191f Fix typo in Sequence.constrainOnce() doc 2021-07-20 14:09:24 +00:00
Mikhael Bogdanov
ff26a471b4 Update diagnostics test affected by ApproximateIntegerLiteralTypesInReceiverPosition and ProhibitSimplificationOfNonTrivialConstBooleanExpressions features 2021-07-20 12:19:57 +00:00
Mikhael Bogdanov
fd605a13d7 Update box tests affected by ApproximateIntegerLiteralTypesInReceiverPosition feature 2021-07-20 11:42:29 +00:00
Andrey Zinovyev
6ef4523555 [FIR] Cache callable names in some composite scopes 2021-07-20 14:25:16 +03:00
Andrey Zinovyev
15be38192b [FIR] Mark implicit types in accessors as fake
To not check their types in deprecation checker
2021-07-20 14:25:14 +03:00
Yahor Berdnikau
caa6b630ab Apply 'kotlin-android' plugin dynamically.
Only apply when one of android plugins are also applied to the project.

If none of AGP plugins are applied and 'kotlin-android' is - exception
 in 'afterEvaluate {..}' will be thrown.

^KT-46626 Fixed
2021-07-20 13:44:45 +03:00
Dmitriy Novozhilov
f3116cb64a Fix NON_EXHAUSTIVE_WHEN_STATEMENT warnings in project code 2021-07-20 13:33:46 +03:00
Dmitriy Novozhilov
a6edd852ff [FIR] Report NON_EXHAUSTIVE_WHEN_STATEMENT/NO_ELSE_IN_WHEN for when's on logical types
^KT-47709 In Progress
2021-07-20 13:33:44 +03:00
Dmitriy Novozhilov
ef635f6a96 [FE 1.0] Report NON_EXHAUSTIVE_WHEN_STATEMENT/NO_ELSE_IN_WHEN for when's on logical types
^KT-47709 In Progress
2021-07-20 13:33:43 +03:00
Dmitriy Novozhilov
85c7f386eb Add Kotlin 1.7 language version 2021-07-20 13:33:41 +03:00
Andrey Zinovyev
4a37de51bb [FIR] Add ANONYMOUS_INITIALIZER_IN_INTERFACE diagnostic 2021-07-20 13:29:00 +03:00
Yahor Berdnikau
304d01127f Fix false positive on Java/Kotlin JVM target validation.
Fix false positive case when java toolchain was set to <JDK1.8. In such
case Java tasks return '8' (or less) for target instead of '1.8'.

^KT-47520 Fixed
2021-07-20 09:25:06 +00:00
nataliya.valtman
f76864260a Log changed files into ES statistic 2021-07-20 11:26:55 +03:00
Dmitriy Novozhilov
9b3b386f0a [FIR IDE] Ignore HMMP compiler test 2021-07-20 10:33:54 +03:00
Dmitriy Novozhilov
749dbf4d44 [FIR] Safe dependency symbol provider in IDE session 2021-07-20 10:33:53 +03:00
Dmitriy Novozhilov
37c096cb10 [FIR] Support creation of IR of common + platform sources in FirAnalyzerFacade 2021-07-20 10:33:52 +03:00
Dmitriy Novozhilov
df11ccf755 [FIR] Fix dependency on jvm descriptors for running fir2ir tests with JPS 2021-07-20 10:33:51 +03:00
Dmitriy Novozhilov
5354e4afe4 [FIR] Ignore some MPP backend tests
FIR doesn't support actual declarations in same module where expect
  declarations lay
2021-07-20 10:33:50 +03:00
Dmitriy Novozhilov
c3060e861f [FIR] Add expect actual checker 2021-07-20 10:33:49 +03:00
Dmitriy Novozhilov
faadb08174 [FIR-IDE] Fix generating conversions for pair with non-trivial converters 2021-07-20 10:33:48 +03:00
Dmitriy Novozhilov
b363d95160 [FIR-IDE] Add conversion for Map type 2021-07-20 10:33:47 +03:00
Dmitriy Novozhilov
3b2df7ade3 [FIR] Inherit expect modifier from outer classes 2021-07-20 10:33:46 +03:00
Dmitriy Novozhilov
18af4155b8 [FIR] Properly infer open modality for functions of expect interfaces 2021-07-20 10:33:45 +03:00
Dmitriy Novozhilov
3991383853 [FIR] Provide compiler light classes from all source modules 2021-07-20 10:33:44 +03:00
Dmitriy Novozhilov
8729421e7a [FIR] Add kind to all FirSessions 2021-07-20 10:33:43 +03:00
Dmitriy Novozhilov
2c1ada131d [FIR] Don't generate implicit primary constructor for expect classes 2021-07-20 10:33:42 +03:00
Dmitriy Novozhilov
b1e47a46cd [FIR] Inherit isExpect flag of members from containing class 2021-07-20 10:33:41 +03:00
Dmitriy Novozhilov
9fd25af1a7 [FIR] Add pretty toString to FirSession and ModuleData 2021-07-20 10:33:40 +03:00
Dmitriy Novozhilov
55775a7beb [FIR] Use proper moduleData in fake override generator 2021-07-20 10:33:38 +03:00
Dmitriy Novozhilov
7f20b83159 [FIR] Use proper moduleData in synthetic properties scope 2021-07-20 10:33:37 +03:00
Dmitriy Novozhilov
7008f02962 [FIR] Create fir classes for java annotations and enums with Final modality 2021-07-20 10:33:34 +03:00
Dmitriy Novozhilov
6e83820f97 Move ExpectActualCompatibility to :compiler:resolution.common 2021-07-20 10:33:33 +03:00
Dmitriy Novozhilov
950db81aa4 [FIR] Split compileModulesUsingFrontendIR to multiple functions 2021-07-20 10:33:32 +03:00
Dmitriy Novozhilov
ec1651df92 [FIR] Store dependencies symbol provider as separate session component 2021-07-20 10:33:31 +03:00
Ilya Matveev
1c5361dacd [K/N] disable throwThroughBridge test for wasm32 2021-07-20 07:19:38 +00:00
Hung Nguyen
ecf6001365 KotlinCompile: Prepare for classpath snapshotting and diffing
This commit prepares necessary components only. The core parts of
classpath snapshotting and diffing will be implemented next.

Bug: KT-45777
Test: Existing IncrementalCompilationClasspathSnapshotJvmMultiProjectIT
      and IncrementalJavaChangeClasspathSnapshotIT
2021-07-20 04:04:43 +03:00
Hung Nguyen
41345b2c50 Pass classpath changes from KotlinCompile task to Kotlin compiler
This commit wires necessary components only. The actual classpath
changes will be provided later.

Bug: KT-45777
Test: Existing IncrementalCompilationClasspathSnapshotJvmMultiProjectIT
      and IncrementalJavaChangeClasspathSnapshotIT
2021-07-20 04:04:43 +03:00
Hung Nguyen
c8b3b6df9c KotlinCompile: Set up artifact transform to take classpath snapshot
This commit sets up the artifact transform only. The actual classpath
snapshotting and computation of classpath changes will be done later.

Bug: KT-45777
Test: Existing IncrementalCompilationClasspathSnapshotJvmMultiProjectIT
      and IncrementalJavaChangeClasspathSnapshotIT
2021-07-20 04:04:43 +03:00
Ilmir Usmanov
5517aa36e1 Minor. Add debugger test
#KT-47749
2021-07-19 22:07:17 +00:00
Ilmir Usmanov
e870a200c4 Merge consequent LVT records
that is, if LVT record starts where previous one ends, merge them.
 #KT-47749 Fixed
2021-07-19 22:07:16 +00:00
Ilmir Usmanov
5ae01c8b2a Do not duplicate $result in LVT
#KT-47749
2021-07-19 22:07:16 +00:00
Ilmir Usmanov
b4d356c5bd Split LVT record for known nulls
Since they are not spilled, the logic for splitting LVT records, that
is applied for spilled variables, was not applied for known nulls.
Fix that by applying the logic to them.
 #KT-47749
2021-07-19 22:07:15 +00:00
Mads Ager
83dddd73b0 Always add a local variable for its live ranges.
There used to be code that extended a previous range instead.
However, that does not work as that extension could have the
local cover code where it does not exists. Since we no longer
extend the range of locals, we should always introduce a new
one even if there was another one for a previous range.
2021-07-19 22:07:14 +00:00
Ilya Muradyan
ae650ef19b Add EPL 1.0 licence text for Eclipse Aether dependencies 2021-07-19 21:31:50 +03:00
Ilya Muradyan
46bbe5b1cb Replace Ivy resolver with Maven resolver in all places 2021-07-19 21:31:49 +03:00
Ilya Muradyan
014765a302 Add dependencies-maven-all artifact 2021-07-19 21:31:48 +03:00
Ilya Muradyan
f7c2adae30 Always use wagon classloader as a plexus class world
In CLI compiler, system classloader doesn't load all classes directly,
so wagons (including HttpWagon) happen to be invisible to
Plexus DI that leads to artifacts download failures.
2021-07-19 21:31:46 +03:00
Alexander Likhachev
b93bd1fe09 [Gradle] Simplify optInAnnotation function name to optIn in DSL
#KT-38111
2021-07-19 19:57:00 +03:00
Dmitry Petrov
e276dec4de JVM don't merge local values in FixStackAnalyzer
We care only about stacks there.
This yields about 10-15% in a pathological case such as KT-41510.
2021-07-19 19:24:57 +03:00
Ilya Kirillov
230fce65e5 LL API: add kt -> fir mapping tests for types 2021-07-19 18:45:44 +03:00
Ilya Kirillov
1423aa2c43 LL API: fix kt -> fir mapping of type inside nullable type 2021-07-19 18:45:43 +03:00
Ilya Kirillov
ddd257adc2 LL API: add test for kt -> fir mapping of qualified calls 2021-07-19 18:45:42 +03:00
Ilya Kirillov
3ae1fe69da LL API: add test for kt -> fir mapping 2021-07-19 18:45:41 +03:00
Ilya Kirillov
b380bcfd99 LL API: add kt -> fir mapping tests for expressions 2021-07-19 18:45:40 +03:00
Ilya Kirillov
0554e2a083 LL API: fix kt -> fir mapping for KtStringTemplateEntryWithExpression 2021-07-19 18:45:38 +03:00
Ilya Kirillov
9d53ad4346 LL API: fix kt -> fir mapping for KtObjectLiteralExpression 2021-07-19 18:45:37 +03:00
Ilya Kirillov
32baac52e6 LL API: add kt -> fir mapping tests for property delegation 2021-07-19 18:45:36 +03:00
Ilya Kirillov
831f05a802 LL API: fix kt -> fir mapping for KtImportList 2021-07-19 18:45:35 +03:00
Ilya Kirillov
c266d3e075 LL API: fix kt -> fir mapping for KtValueArgumentList 2021-07-19 18:45:34 +03:00
Ilya Kirillov
f6a97cdec6 LL API: fix kt -> fir mapping for KtValueArgument 2021-07-19 18:45:32 +03:00
Ilya Kirillov
6139d97b2a LL API: allow getOrBuildFir to return null 2021-07-19 18:45:31 +03:00
Ilya Kirillov
4bca296dc6 LL API: introduce helper function for throwing invalid FirElement exception 2021-07-19 18:45:29 +03:00
Ilya Kirillov
c0eb669191 LL API: add basic tests for kt -> fir mapping 2021-07-19 18:45:28 +03:00
Elena Lepilkina
609296a46b [K/N] Use libclang_rt version for simulator for last Xcode versions (KT-47333 fixed) 2021-07-19 14:12:41 +00:00
Mikhael Bogdanov
03ccbf1b17 Upgrade kotlinx-metadata-jvm and binary-compatibility-validator versions 2021-07-19 13:49:05 +00:00
Ilya Chernikov
0cd29adcc7 Get rid of kotlinx-coroutines usage in scripting libs and plugins
the dependency on the coroutines library caused various problems like
KT-30778, or stdlib/runtime version conflicts.
The only function used was `runBlocking`, so this change replaces it
with the internal implementation based on the similar internal thing
from the stdlib.
#KT-30778 fixed
2021-07-19 16:35:36 +03:00
Alexander Udalov
9b1de90452 Cache async-profiler when using -Xprofile 2021-07-19 15:14:57 +02:00
Igor Chevdar
bea82ba2cd [K/N][stdlib] Added @EagerInitialization annotation
It is needed in the lazy top level properties initialization strategy to
revert to the previous strategy at least for the transition period
2021-07-19 17:23:35 +05:00
Mikhael Bogdanov
4de6fd8be2 Prepare NewMultiplatformIT tests for compiler migration to 1.6 2021-07-19 12:15:26 +00:00
Dmitriy Novozhilov
c304363aea [FE 1.0] Report WRONG_ANNOTATION_TARGET on annotations on type arguments
^KT-47772 Fixed
2021-07-19 14:00:24 +03:00
Andrey Zinovyev
046d886850 [FIR] Fix Nothing returning expressions when checking for not null 2021-07-19 13:40:32 +03:00
Andrey Zinovyev
7e9f27436a [FIR] Fix cfg for safe call inside elvis 2021-07-19 13:40:31 +03:00
Andrey Zinovyev
c160511244 [FIR] Basic support for break inside try-finally blocks
Support single try expression only
2021-07-19 13:40:30 +03:00
Andrey Zinovyev
a6984c5198 [FIR] Add NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY diagnostic 2021-07-19 13:40:28 +03:00
Ilmir Usmanov
151478aa27 Raise deprecations of suspend calls with dangling lambda to error
#KT-22562
2021-07-19 08:36:36 +00:00
Dmitry Petrov
d41fc0b599 PSI2IR fix suspend conversion tests
- support chained suspend conversion + SAM conversion
- support suspend conversion in vararg elements
2021-07-17 09:10:19 +03:00
Victor Petukhov
0cc6fbbc6e Add tests for converting expressions of function types to suspending functional types 2021-07-17 09:10:17 +03:00
Viacheslav Kormushkin
780b9a032b Link CocoaPods frameworks with iosTest binary
#KT-44857 #KT-37513
2021-07-16 19:42:24 +00:00
Mads Ager
b51ff799cb Fix IteratorNext intrinsic to cast its dispatch receiver to
the expected type.

^KT-47741 Fixed.
2021-07-16 21:07:11 +02:00
Ilya Kirillov
f83cc69379 HL API: hacky fix garbage collected diagnostic in call 2021-07-16 21:06:05 +03:00
Ilya Kirillov
d7f1353d3d HL API: update resolve call tests 2021-07-16 21:06:04 +03:00
Ilya Kirillov
44812ae45a HL API: update symbols testdata after adding hasStableParameterNames to function symbol 2021-07-16 21:06:03 +03:00
Mark Punzalan
cb85fd26f5 FIR IDE: Expand KtCall API to include annotation calls and delegated
constructor calls.
2021-07-16 21:06:02 +03:00
Mark Punzalan
d30d8037cf FIR IDE: Add KtFunctionLikeSymbol.hasStableParameterNames. 2021-07-16 21:06:00 +03:00
Mark Punzalan
5c111f8979 FIR IDE: Add argument mapping to KtFunctionCall. 2021-07-16 21:05:59 +03:00
Alexander Likhachev
6fe730a12e [Gradle, JS] Add IT that no tasks configured on help task execution
#KT-47559 Fixed
2021-07-16 20:14:51 +03:00
Alexander Likhachev
0740d11378 [Gradle, JS] Configure run tasks lazily
#KT-47559 In Progress
2021-07-16 20:14:49 +03:00
Victor Petukhov
6a1ec92d39 Introduce specific error for calls which could be resolved only with unrestricted builder inference
^KT-47747 Fixed
2021-07-16 19:32:36 +03:00
Victor Petukhov
357fda2efa Initialize builder inference lambda anyway, even a call is inapplicable
^KT-47744 Fixed
2021-07-16 19:32:35 +03:00
Alexander Likhachev
2b0ba6fa40 [Gradle, MPP] Add test for KT-47611, KT-47612
#KT-47611 Fixed
#KT-47612 Fixed
2021-07-16 18:33:45 +03:00
Alexander Likhachev
8109b66a79 [Gradle, MPP] Make publishing compatible with configuration cache
Capture artifact coordinates more accurately to conform with configuration cache
#KT-47611 In Progress
2021-07-16 18:33:45 +03:00
Alexander Likhachev
77471c0cd8 [Gradle, MPP] Make kotlin tooling metadata task compatible w/ conf cache
The value should be memoized in task, so it can be serialized in a way to not use project in execution time
#KT-47612 In Progress
2021-07-16 18:33:43 +03:00
Mikhael Bogdanov
5f53a2071d Update test affected by ProperTypeInferenceConstraintsProcessing feature 2021-07-16 13:26:37 +00:00
Mikhael Bogdanov
392dce9a40 Update test affected by PrivateInFileEffectiveVisibility feature 2021-07-16 13:26:36 +00:00
Mikhael Bogdanov
c519003e13 Update test affected by ProhibitSimplificationOfNonTrivialConstBooleanExpressions feature 2021-07-16 13:26:36 +00:00
Mikhael Bogdanov
a657e63dbb Update test affected by ForbidUsingExtensionPropertyTypeParameterInDelegate feature 2021-07-16 13:26:35 +00:00
Mikhael Bogdanov
70df4f10c5 Update test affected by AbstractClassMemberNotImplementedWithIntermediateAbstractClass feature 2021-07-16 13:26:34 +00:00
Mikhael Bogdanov
f05d470f6a Update test affected by 'ProhibitJvmFieldOnOverrideFromInterfaceInPrimaryConstructor' feature 2021-07-16 13:26:33 +00:00
pyos
f5dd5ead1f JVM: produce a better error on @JvmStatic external in interface
Java does not permit `static native` methods in interfaces, so this
never worked on any existing JRE.

 #KT-43696 Fixed
2021-07-16 15:24:09 +02:00
pyos
ad7ed483f3 JVM_IR: copy correspondingProperty of static external functions
Required for correctly mapping their names.

 #KT-47715 Fixed
2021-07-16 15:24:05 +02:00
Ilya Goncharov
adeb2f527b [Gradle, JS] Fail incremental test if there is source maps warning
^KT-47751 fixed
2021-07-16 15:39:52 +03:00
Ilya Goncharov
f73726c330 [Gradle, JS] Ignore source maps arguments in cache building
^KT-47751 fixed
2021-07-16 15:39:50 +03:00
Yahor Berdnikau
d82681889b Ignore empty directories on input properties hash calculation.
Annotate all '@InputFiles' and '@InputDirectory' input properties
with '@IgnoreEmptyDirectories' annotation, so empty directories
will be excluded from input hash calculation.

^KT-27687 Fixed
2021-07-16 12:35:15 +00:00
Dmitriy Novozhilov
22f57220c1 [FE 1.0] Report INTEGER_OPERATOR_RESOLVE_WILL_CHANGE on rhs of assign
^KT-47729 Fixed
2021-07-16 15:18:46 +03:00
Dmitriy Novozhilov
afb7625d0c [FE 1.0] Fix false positive INTEGER_OPERATOR_RESOLVE_WILL_CHANGE
^KT-47729 In progress
2021-07-16 15:18:44 +03:00
Dmitriy Novozhilov
2fb5f776d8 [FE 1.0] Report INTEGER_OPERATOR_RESOLVE_WILL_CHANGE on calls in parenthesis
^KT-47729 In progress
2021-07-16 15:18:38 +03:00
Victor Petukhov
ea4ab46765 Report implicit inferred Nothing only for own type parameters and in delegation resolve
^KT-47724 Fixed
2021-07-16 11:21:51 +03:00
Alexander Likhachev
7bb4612149 [Gradle] Add IT that useExperimentalAnnotation produces deprecation warn
#KT-38111 Fixed
2021-07-16 11:01:15 +03:00
Alexander Likhachev
68ced78d89 [Gradle] Rename experimental annotations to opt-in in test data
#KT-38111 In Progress
2021-07-16 11:01:14 +03:00
Alexander Likhachev
fa68dbc736 [Gradle] Rename experimental annotations to opt-in annotations in DSL
Methods and accessors with old names are preserved in public API and marked as deprecated now
#KT-38111 In Progress
2021-07-16 11:01:12 +03:00
Aleksei.Cherepanov
d9701d57bb Fix JPS tests after 2d65383a 2021-07-16 05:35:05 +03:00
Ilya Chernikov
c83614386e [minor] FIR: (temporarily) fix testdata due to different builtins behavior 2021-07-16 02:24:45 +03:00
Ilya Chernikov
02bf745eef IR: Remove some unused IrBuiltIns methods 2021-07-16 02:24:44 +03:00
Ilya Chernikov
51dc829aae IR: Move unsigned classes loading from builtins back to symbols
see #KT-47540 for the motivation
2021-07-16 02:24:43 +03:00
Ilya Chernikov
808f5148f3 IR: implemented generic knownBuiltIns property 2021-07-16 02:24:42 +03:00
Ilya Chernikov
a7d494480c [minor] FIR: minor fixes in FIR-based IrBuiltIns 2021-07-16 02:24:41 +03:00
Ilya Chernikov
56805dded8 [minor] IR: minor builtins infrastructure fixes 2021-07-16 02:24:40 +03:00
Ilya Chernikov
19f52d9aae [minor] FIR: fix irbuiltins implementation after rebase 2021-07-16 02:24:38 +03:00
Ilya Chernikov
873a7c6ef1 FIR: Implement delayed binding of overriddens in the delegated members
fixes the problem when overridden symbols on delegated members were
build on the incomplete fake overrides leading to the incorrect
generation of the function for default parameter and thus to the
codegen error (see withDefaultsMultipleFilesOrder test for an example)
2021-07-16 02:24:37 +03:00
Ilya Chernikov
c9b6847d83 FIR: Add test on delegated member with default param in overridden...
sensitive to the file processing order, therefore failing on the
current fir2ir at least with the new irBuiltIns
2021-07-16 02:24:36 +03:00
Ilya Chernikov
a2385b5edd [minor] FIR: Fix Fir2ir jvmmappedscope functions origins 2021-07-16 02:24:35 +03:00
Ilya Chernikov
6001a81a30 [minor] FIR: Fix IR builtins modality 2021-07-16 02:24:34 +03:00
Ilya Chernikov
5b2acea98f FIR: Add analysis flag for loading IR builtins from sources 2021-07-16 02:24:32 +03:00
Ilya Chernikov
c2c02ddb27 FIR: refactoring IrBuiltIns initialization logic...
to allow to try to load them from dependencies first
and to intialize fake overrides properly
2021-07-16 02:24:31 +03:00
Ilya Chernikov
9de27bc4d8 FIR: Avoid "Mutating Fir2Ir lazy elements" error
for classes came from sources
2021-07-16 02:24:30 +03:00
Ilya Chernikov
8f5d5c3ace FIR: Fixes in testdata after implementing FIR-specific IrBuiltIns 2021-07-16 02:24:29 +03:00
Ilya Chernikov
01f26ec699 FIR: Switch to FIR-based IrBuiltIns in FIR compilation
get rid of using old FE for builtins on FIR compilation
2021-07-16 02:24:28 +03:00
Ilya Chernikov
3b20ec46ef FIR: Set correct modality to default accessors on deserialization
fixes some tests with new IrBuiltIns
2021-07-16 02:24:27 +03:00
Ilya Chernikov
5b677c068f FIR: Refactor JvmMappedScope to fix container-related tests with new builtins 2021-07-16 02:24:25 +03:00
Ilya Chernikov
80a710a5c5 FIR: implementing IrBuiltIns over FIR 2021-07-16 02:24:24 +03:00
Ilya Chernikov
cb4999f23c Native: port native to the new IrBuiltIns 2021-07-16 02:24:22 +03:00
Ilya Chernikov
48a3c64901 IR: Refactor primitive arrays handling in the new IrBuiltIns
for better compatibility e.g. with native
2021-07-16 02:24:20 +03:00
Ilya Chernikov
3b2bb2ba9f IR: Fix error rendering on IR symbol binding conflict
it could be called with uninitialized `owner` parameter, leading
to the NPE on render
2021-07-16 02:24:19 +03:00
Ilya Chernikov
dee0487185 IR: Refactor IrBuiltIns to abstract it from descriptors 2021-07-16 02:24:18 +03:00
Nikolay Lunyak
25d2e61a82 [FIR2IR] Adding 2 new runners for fir2ir-specific tests 2021-07-15 23:15:39 +03:00
Alexander Likhachev
a6e477fa88 [Build] Add dependency verification data for jna 2021-07-15 20:41:59 +03:00
Alexander Likhachev
1a77b57a7b [Gradle] Provide JNA jar to compiler classpath with intellij-core 203+
#KT-47748 Fixed
2021-07-15 20:41:57 +03:00
Yahor Berdnikau
da1d49e622 Add new ways to set Kotlin daemon JVM arguments.
Additionally to inheriting Gradle daemon arguments or configuring via
 Gradle daemon arguments system property, it is also possible now
 to configure arguments either using "kotlin.daemon.jvmargs" property
 or extension DSL.

Extension DSL overrides special gradle property arguments, which
overrides Gradle daemon arguments.

^KT-45747 Fixed
2021-07-15 17:27:38 +00:00
Dmitry Petrov
b98322c1b4 JVM don't optimize methods with too many TCBs 2021-07-15 20:18:18 +03:00
Dmitry Petrov
d65d66c03a JVM reserve 2 slots for node predecessors/successors in CFG 2021-07-15 20:18:15 +03:00
Dmitry Petrov
6c2d93bb8b JVM traverse nodes in reverse order in 'findSafelyReachableReturns' 2021-07-15 20:18:13 +03:00
Mikhael Bogdanov
f080dbb78c Update resolveAnnotations tests in new infrastructure 2021-07-15 17:08:17 +00:00
Mikhael Bogdanov
671ef7dfff Regenerate tests 2021-07-15 17:08:16 +00:00
Mikhael Bogdanov
3aeb9291fe Move resolveAnnotations tests into diagnostics tests 2021-07-15 17:08:16 +00:00
Jinseong Jeon
9ec4d19a3f FIR IDE: avoid finding symbol for function type parameter 2021-07-15 18:29:33 +02:00
Jinseong Jeon
2e502bd01e FIR IDE: fix anonymous function symbol retrieval from function literal 2021-07-15 18:29:32 +02:00
Dmitry Petrov
8ea4916d64 JVM_IR KT-47739 recognize fake override external stubs 2021-07-15 19:20:39 +03:00
Ivan Kochurkin
dd54338ec0 [FIR] Fix positioning and detecting of WRONG_NUMBER_OF_TYPE_ARGUMENTS
Refactor code and fix compilation errors caused by changes to symbol.fir
2021-07-15 19:02:58 +03:00
Ivan Kochurkin
345152d198 [FIR] Add containingDeclarationSymbol to FirTypeParameter 2021-07-15 19:02:56 +03:00
Ivan Kochurkin
0c25d280ee [FIR] Fix calculating of source of TypeArgumentList, add source to FirQualifierPart
Fix positioning for TYPE_ARGUMENTS_NOT_ALLOWED
2021-07-15 19:02:54 +03:00
Ivan Kochurkin
28a6928873 [FIR] Check rest OUTER_CLASS_ARGUMENTS_REQUIRED diagnostics on checkers stage
Add FirOuterClassArgumentsRequiredChecker
2021-07-15 19:02:45 +03:00
Ivan Kochurkin
0fc8be4d60 [FIR] Implement OUTER_CLASS_ARGUMENTS_REQUIRED diagnostics 2021-07-15 19:02:40 +03:00
Yahor Berdnikau
f7ed2f813d Exclude Gradle Kotlin runtime dependencies from 'no-arg' plugin.
This should remove warnings on multiple versions in build classpath
runtime.

^KT-47635 Fixed
2021-07-15 15:27:56 +00:00
Yahor Berdnikau
8db1c52c09 Exclude Gradle Kotlin runtime from 'sam-with-receiver' plugin.
This should remove warnings on multiple dependencies versions
in the build classpath runtime.

^KT-47636 Fixed
2021-07-15 15:27:24 +00:00
Mikhail Glukhikh
40c3c317b2 RawFirBuilder: optimize package name calculation in compiler mode 2021-07-15 12:46:23 +00:00
Ilya Goncharov
dcc54101a7 [Gradle, JS] Add test with icremental JS Ir in parallel build 2021-07-15 11:42:48 +00:00
Svyatoslav Kuzmich
a468792a19 [Wasm] Support Milestone 3 of V8 Wasm GC
Advance V8 version to 9.2.212

Relevant Wasm GC changes:
f9f8ffa445
2021-07-15 10:59:06 +00:00
sebastian.sellmair
9500b2d36e [Commonizer] Add HierarchicalCInteropCallableAnnotationCommonizationTest.test single platform not marked as objc 2021-07-15 10:04:45 +00:00
sebastian.sellmair
17ed498390 [Commonizer] approximationKeys: Fix closing ] for type parameter types' upper bounds 2021-07-15 10:04:45 +00:00
sebastian.sellmair
daa046589e [Commonizer] approximationKeys: Minor cleanup of buildApproximationSignature 2021-07-15 10:04:44 +00:00
sebastian.sellmair
2c8ce2539b [Commonizer] HierarchicalPropertyCommonizationTest: Add test property with and without setter 2021-07-15 10:04:43 +00:00
sebastian.sellmair
8bab6c3076 [Commonizer] Commonize 'val' and 'var' properties
If a setter is not present on all platforms a fallback private setter
shall be emitted.

^KT-47502 Verification Pending
^KT-47691 Verification Pending
2021-07-15 10:04:43 +00:00
sebastian.sellmair
c4d90dc744 [Commonizer] Implement alis type substitution as CirNodeTransformer
This has the advantage, that the substitution only has to run on
functions or properties that are 'incomplete' (missing at least
one other target declaration)

^KT-47433 Verification Pending
2021-07-15 10:04:42 +00:00
sebastian.sellmair
7c450f9884 [Commonizer] Implement CirAliasTypeSubstitutor
This will substitute non-commonizable classifiers with known
type-aliases (which might be commonizable).

A simple example depending on this substitution comes from posix:
Most function and properties use the `FILE` typealias which
is available across all platforms.

Some linux platforms use `__IO_FILE` in their signature, which
is just linux specific. This type substitution will figure out, that
this type can be substituted with `FILE`.

^KT-47433 Verification Pending
2021-07-15 10:04:41 +00:00
sebastian.sellmair
906346b7d9 [Commonizer] Drop CirProperty interface for plain data class 2021-07-15 10:04:41 +00:00
sebastian.sellmair
f0feca286e [Commonizer] Drop CirExtensionReceiver interface for plain data class 2021-07-15 10:04:40 +00:00
sebastian.sellmair
fdee49ee59 [Commonizer] Drop CirTypeParameter interface for plain data class 2021-07-15 10:04:39 +00:00
sebastian.sellmair
4a4516731a [Commonizer] Drop CirValueParameter interface for plain class 2021-07-15 10:04:39 +00:00
sebastian.sellmair
e246a12cd3 [Commonizer] Drop CirFunction interface for plain data class 2021-07-15 10:04:38 +00:00
sebastian.sellmair
0c32abed02 [Commonizer] Remove now unnecessary ArtificialCirDeclaration
This marker interface is not necessary anymore, since no new actuals
will be generated by the Commonizer. It was used to filter declarations
during the serializ
2021-07-15 10:04:37 +00:00
sebastian.sellmair
e041532dd2 [Commonizer] InlineSourceBuilder: Also mark ModuleBuilder functions with InlineSourcesCommonizationTestDsl 2021-07-15 10:04:37 +00:00
sebastian.sellmair
87ac436a35 [Commonizer] Implement HierarchicalCInteropCallableAnnotationCommonizationTest 2021-07-15 10:04:36 +00:00
sebastian.sellmair
8acfeb3e17 [Commonizer] Remove computing signatures from metadata 2021-07-15 10:04:36 +00:00
sebastian.sellmair
f3ff9814a8 [Commonizer] Create approximation keys based on Cir instead of metadata 2021-07-15 10:04:35 +00:00
sebastian.sellmair
09f9a1ce5b [Commonizer] Share Test: Commonizer / Light run configuration
This run configuration can be used to run only light weight/faster tests
2021-07-15 10:04:34 +00:00
Andrey Kuleshov
26a71af6b3 [Native, All platforms] HotFix of the incorrect parsing of long strings to Float and Double (#4492)
### What's done:
- Fixed incorrect logic of String.toFloat() and String.toDouble().
  Long string without any digits were treated as Float or Double:
  "this string does not look as float isn't it?".toFloat() == "Infinity".

- Fixed incorrect parsing of floating point constants "NaN" and "Infinity":
  String values like "NaNPICEZy" or "InfinityN" were treated as valid numbers.

- Merged parsing logic for Double and Float:
  Removed the code duplication, unified methods, made the code more Kotlin-like, not C++-like.

- Updated tests:
  Removed useless tests that checked nothing, updated tests with regression scenarios.
2021-07-15 14:47:55 +07:00
Sergey Bogolepov
118889add5 [K/N] Fix mingw_x86 compilation
It was broken in 9ed97a27f1.
2021-07-15 04:55:36 +00:00
Roman Artemev
447900c3f2 [K/N] Make sure all module names are uniq
In case of klib -> binary compilation there were two different modules
with the same. It breaks invariant about uniqueness if module name.
2021-07-15 03:09:46 +03:00
Georgy Bronnikov
ba61700be6 Regenerate tests 2021-07-14 21:20:49 +03:00
Georgy Bronnikov
4af2aaedb1 IR, temporary: a simpler mangling for flexible types
Mangling for flexible types will need another look.
Complicated cases still do not work.
2021-07-14 21:20:48 +03:00
Georgy Bronnikov
c3f4fcde0b JVM_IR: compute signatures for fake overrides of Java fields 2021-07-14 21:20:47 +03:00
Georgy Bronnikov
8c3386b607 IR: set file in declarationTable when serializing IR 2021-07-14 21:20:46 +03:00
Georgy Bronnikov
05a42b8cd5 IR: handle CompositeSignature in DescriptorByIdSignatureFinder 2021-07-14 21:20:45 +03:00
Georgy Bronnikov
da946e464f Fix compilation after rebase: add debugInfo to JvmIr.proto 2021-07-14 21:20:43 +03:00
Georgy Bronnikov
f4d358069c Fixes after rebase, not related to IrLibraryFile 2021-07-14 21:20:42 +03:00
Georgy Bronnikov
08b950fc2a JVM_IR: Supply fake file name to signatures of file local declarations 2021-07-14 21:20:41 +03:00
Georgy Bronnikov
225705a237 IR: do not serialize nonlocal initializers in inline-only mode 2021-07-14 21:20:40 +03:00
Georgy Bronnikov
28bff2ba4f JVM_IR: add test for calling monitorEnter/Exit from serialized code. 2021-07-14 21:20:38 +03:00
Georgy Bronnikov
dffb22de9d JVM_IR: avoid duplication in declaration lists during deserialization 2021-07-14 21:20:36 +03:00
Georgy Bronnikov
fa4efd3303 JVM_IR: fix deserialization of Java static field symbols 2021-07-14 21:20:35 +03:00
Georgy Bronnikov
955ee07517 IR: compute signature for scripts 2021-07-14 21:20:33 +03:00
Georgy Bronnikov
9d0c6fb157 IR: remove an overly optimistic assert 2021-07-14 21:20:32 +03:00
Georgy Bronnikov
c3a94e1e62 FIR: adapt to changes in IR interface
JvmGeneratorExtensionsImpl, JvmIrCodegenFactory need new arguments.
2021-07-14 21:20:31 +03:00
Georgy Bronnikov
20b76d4149 JVM_IR: reorganize initialization of JvmGeneratorExtensionsImpl
CachedFields are now created at initialization.
Therefore we need CompilerConfiguration as a constructor parameter.
2021-07-14 21:20:30 +03:00
Georgy Bronnikov
7bbc04b6a2 JVM_IR: reconstruct fake overrides after IR deserialization.
We need to keep track of local signatures for deserialized symbols.
2021-07-14 21:20:29 +03:00
Georgy Bronnikov
a63cc95a2a JVM_IR: untangle backend.jvm and serialization.jvm (again) 2021-07-14 21:20:28 +03:00
Georgy Bronnikov
1c4466951f IR: a flag to GeneratorExtensions to control IR deserialization
There is no need to search for IR embedded in toplevel classes when none
is expected (in npon-JVM backends or when -Xserialize-ir is not set).
2021-07-14 21:20:27 +03:00
Georgy Bronnikov
ec1c97c684 JVM_IR: register builtin annotation constructors in SymbolTable
When deserializing IR, these annotations need to be visible.
2021-07-14 21:20:26 +03:00
Georgy Bronnikov
8d15a1d13d JVM_IR: use signatures in AbstractIrSerializeCompileKotlinAgainstInlineKotlinTest
Using signatures allows us to identify calls from a new module to an old
one.
2021-07-14 21:20:24 +03:00
Georgy Bronnikov
49619cda48 Restore Native compilation 2021-07-14 21:20:23 +03:00
Georgy Bronnikov
931733f8cc JVM_IR: deal with JvmStatic in imported IR 2021-07-14 21:20:22 +03:00
Georgy Bronnikov
96ce124268 JVM_IR: serialize fake overrides in IR 2021-07-14 21:20:21 +03:00
Georgy Bronnikov
2d3a558d50 JVM_IR: normalize visibility before serializing 2021-07-14 21:20:20 +03:00
Georgy Bronnikov
a328ebc889 JVM_IR: extract cached fields into a separate class 2021-07-14 21:20:18 +03:00
Georgy Bronnikov
50068607b9 JVM_IR: call serializeIr from a phase
This circumvents the need to run expect/actual resolution on
deserialized IR.
2021-07-14 21:20:17 +03:00
Georgy Bronnikov
0d5fe0b029 JVM_IR: load serialized data for every affected property of IrLazyFunction 2021-07-14 21:20:16 +03:00
Georgy Bronnikov
f4e6eb00fd JVM_IR: generate unbound symbols after deserializing IR 2021-07-14 21:20:15 +03:00
Georgy Bronnikov
6b80c00cc6 JVM_IR: deserialize lazy declarations 2021-07-14 21:20:14 +03:00
Georgy Bronnikov
ad8892f71f JVM_IR: test that inline functions have deserialized bodies 2021-07-14 21:20:12 +03:00
Georgy Bronnikov
7b52a8c07d JVM_IR: deal with facade classes when computing signature 2021-07-14 21:20:11 +03:00
Georgy Bronnikov
97d3eda23c JVM_IR: run Kotlin against Kotlin tests with serialization 2021-07-14 21:20:10 +03:00
Georgy Bronnikov
ab3d6490ed JVM_IR: save auxTables as byte strings 2021-07-14 21:20:09 +03:00
Georgy Bronnikov
7dbdb311e1 JVM_IR: read serialized IR from annotation 2021-07-14 21:20:08 +03:00
Georgy Bronnikov
baaecaa052 JVM_IR: write serialized IR to an annotation 2021-07-14 21:20:06 +03:00
Georgy Bronnikov
b177779b66 IR: compute signatures for fields 2021-07-14 21:20:05 +03:00
Georgy Bronnikov
b2617199bc JVM_IR: call serialization for IR.
Serializer for IR is called when -Xserialize-ir flag is set.
2021-07-14 21:20:04 +03:00
Georgy Bronnikov
9efd0d7589 JVM_IR: JvmIrSerializer 2021-07-14 21:20:02 +03:00
Mikhail Glukhikh
113d2653aa Drop deprecated -Xexperimental flag from compiler and tests 2021-07-14 21:18:23 +03:00
anastasiia.spaseeva
cbcec8d624 Add changelog for 1.5.21 2021-07-14 19:37:14 +03:00
Margarita Bobova
ed3326fd83 Add changelog for 1.5.20 2021-07-14 19:37:12 +03:00
Nikita Bobko
bf6718e0a5 Fix compilation in kotlin-ide 2021-07-14 17:17:19 +02:00
Ilya Goncharov
047041dc6e [Gradle, JS] Await worker which builds cache 2021-07-14 14:46:04 +00:00
Pavel Kunyavskiy
92789984e0 [K/N] Make SafeContinuation thread-safe 2021-07-14 09:03:31 +00:00
pyos
07cb3a5ff8 JVM: do not reify methods of objects in lambdas
All type parameters used in them are not from the inline function
anyway.
2021-07-14 10:11:05 +02:00
pyos
717cf2066a JVM: remove more redundant properties from LambdaInfo 2021-07-14 10:11:05 +02:00
pyos
c1c56ca388 JVM: refactor extraction of default inline lambdas a bit more 2021-07-14 10:11:05 +02:00
pyos
91cf1a1a4d JVM: remove a redundant DefaultLambda field
and add a comment explaining one branch of the inliner... Better than
nothing, I guess?
2021-07-14 10:11:05 +02:00
pyos
100d2d629c JVM: inline default lambda coercions from bridge invoke
The type of the default lambda may be a subtype of the parameter type,
so we can't really generate our own coercions at all as we don't know
the precise Kotlin type of the `invoke` method.
2021-07-14 10:11:05 +02:00
pyos
d0b9c4ae6b JVM: generalize getMethodNode
to allow matching by arbitrary predicates.
2021-07-14 10:11:05 +02:00
Alexander Likhachev
f986591ba9 [Build] Suppress ivy url senseless comparison warning
It's marked as not null in Gradle, but it's still possible to declare Ivy repository with null url which leads to GeneralKotlin2JsGradlePluginIT#testJsBothModeWithTests test false fail (cache redirector script is used in Gradle integration tests)
2021-07-14 10:59:14 +03:00
Ilya Matveev
922aad6865 [K/N] Add exp10 and exp10f to good function list for call checker
Clang may replace a call to `pow (10.0, x)` with a call to `exp10(x)`
(or `__exp10` on MacOS).

We use this function in float parsing logic, so this function should
be added to the good function list.
2021-07-14 04:49:04 +00:00
Nikolay Krasko
0f2e653625 Use cache-redirector for yarn download (KTI-577) 2021-07-13 22:36:51 +03:00
Nikolay Krasko
ec04af9eea Update cache redirector list 2021-07-13 22:36:50 +03:00
Dmitry Petrov
dc16d66fb1 Minor: regenerate tests 2021-07-13 21:23:17 +03:00
pyos
3dc7b6c3ee IR: preserve argument evaluation order more carefully
1. receivers should be evaluated before named arguments;
 2. just because an argument has no side effects doesn't mean it is not
    affected by the other arguments' side effects - in that case it
    should still be evaluated in source order.

 #KT-47660 Fixed
2021-07-13 21:23:15 +03:00
Roman Artemev
b5942204dc [KLIB] Enable accidentally disabled IC for klibs in K/JS 2021-07-13 18:58:57 +03:00
Roman Artemev
ece9307471 [JS IR] Fix destination directory in Incremental compiler runner for JS 2021-07-13 18:58:56 +03:00
Aleksei.Cherepanov
d2881a7920 Improve performance of Lookup storage
Reduce size of lookup map after rebuild, reduce waiting time by replacing operations of read+write with append, also split remove garbage process into smaller operations in get

#KT-46804 Fixed
2021-07-13 18:39:38 +03:00
Alexander Udalov
35f6337de3 Remove obsolete kotlin.build.useIR flag
(cherry picked from commit 91e47f1fd7)
2021-07-13 14:01:19 +02:00
Elena Lepilkina
c401cf961d [K/N][C interop] Support Kotlin special names processing (KT-47209 fixed) 2021-07-13 11:56:31 +00:00
Roman Artemev
0326518fc9 [KLIB] Cutting down usages of moduleDescriptor in linker
Replace map key `ModuleDescriptor` with `String` which is module name
2021-07-13 14:43:42 +03:00
Roman Artemev
eadf252de9 [KLIB] Provide KotlinLibrary for Konan Interop Deserializer 2021-07-13 14:43:41 +03:00
Roman Artemev
0a49b24320 [JS IR] Move klib resolution from cli into compiler
Simplify CLI -> Compiler API
Clean up code
2021-07-13 14:43:40 +03:00
Roman Artemev
103e4ef2a5 [JS IR] Disable ts export check in PIR mode in box tests
Since that feature is not declared as working yet
2021-07-13 14:43:38 +03:00
Elena Lepilkina
025e572462 [K/N] Fixed case with parameter which can be optimized with BCE 2021-07-13 09:22:13 +00:00
Elena Lepilkina
2477ea80c6 Reverted loops order processing in ForLoopsLowering 2021-07-13 09:22:12 +00:00
Elena Lepilkina
c096e6a3eb [K/N] Analyze vals in bounds check elimination 2021-07-13 09:22:11 +00:00
Elena Lepilkina
9503627864 Changed an order of processing loops in ForLoopsLowering 2021-07-13 09:22:11 +00:00
Elena Lepilkina
0e04c21625 [K/N] Bounds check elimination in basic for loops forms 2021-07-13 09:22:10 +00:00
Elena Lepilkina
7975311ca2 [K/N] Added tests for bounds checks 2021-07-13 09:22:09 +00:00
Elena Lepilkina
ac074207c7 [K/N] ForLoopsLowering: Use get without bounds check in ArrayIterationHandler 2021-07-13 09:22:08 +00:00
Dmitriy Novozhilov
f33f3c769f Fix USELESS_IS_CHECK warnings in compiler code 2021-07-13 10:35:05 +03:00
Dmitriy Novozhilov
968f823b72 [JVM IR]Fix detecting annotation retention 2021-07-13 10:35:04 +03:00
Dmitriy Novozhilov
47b0071560 [FE 1.0] Properly handle intersection types in check if cast possible or not
^KT-47685 Fixed
2021-07-13 10:35:03 +03:00
Dmitriy Novozhilov
f0c4d06fc9 [FE 1.0] Cleanup PatternMatchingTypingVisitor.kt 2021-07-13 10:35:02 +03:00
Dmitriy Novozhilov
7b5a5f5682 [FE 1.0] Report USELESS_IS_CHECK if is expression is always false
^KT-47684 Fixed
2021-07-13 10:35:01 +03:00
Dmitriy Novozhilov
785e2f862c [PSI] Ignore when failed to get file text
This is change from 36ff952 which was forgotten when applying 203 bunch
2021-07-13 10:34:59 +03:00
Dmitriy Novozhilov
daa4c708a2 [FIR] Remove unused parameter from ensureResolvedForCalls 2021-07-13 10:31:36 +03:00
Dmitriy Novozhilov
c3b20c9ccb [FIR IDE] Add forgotten space to renderer in diagnostic generator 2021-07-13 10:31:34 +03:00
Dmitriy Novozhilov
22a4da024b [FIR] Fix all illegal usages of symbol.fir in checkers module 2021-07-13 10:31:34 +03:00
Dmitriy Novozhilov
e94d75d433 [FIR] Add opt-in annotation which prevents from using symbol.fir 2021-07-13 10:31:32 +03:00
Dmitriy Novozhilov
c99a02796f [FIR] Replace getContainingClass usages with getContainingClassSymbol 2021-07-13 10:31:31 +03:00
Dmitriy Novozhilov
48a25e2fe6 [FIR] Add some status utils over symbols to addition to utils over fir 2021-07-13 10:31:30 +03:00
Dmitriy Novozhilov
b2c6dd8d53 Convert ClassKind.java to Kotlin 2021-07-13 10:31:29 +03:00
Dmitriy Novozhilov
0062f1ba27 Rename ClassKind.java to ClassKind.kt 2021-07-13 10:31:28 +03:00
Dmitriy Novozhilov
22938522b3 [FIR] Add forgotten updating phase of value parameters 2021-07-13 10:31:27 +03:00
Dmitriy Novozhilov
d3966e8844 [FIR] Add accessors to parts of signatures to symbols 2021-07-13 10:31:26 +03:00
Dmitriy Novozhilov
0f06ab537f [FIR] Remove useSiteSession parameter from ensureResolved 2021-07-13 10:31:25 +03:00
Dmitriy Novozhilov
92cfaf68bb [FIR] Remove unused FirFunctionSymbol.parameters 2021-07-13 10:31:24 +03:00
Dmitriy Novozhilov
4deb935f76 [FIR] Mark value classes as inline in raw fir building 2021-07-13 10:31:23 +03:00
Dmitriy Novozhilov
8df56af068 [FIR] Add forgotten settings of resolve phase 2021-07-13 10:31:22 +03:00
Dmitriy Novozhilov
9f161f16b3 [FIR] Move FirPhaseManager to :compiler:fir:tree 2021-07-13 10:31:21 +03:00
Dmitriy Novozhilov
51fc2e453f [FIR] Unity FirCallableDeclaration and FirCallableMemberDeclaration
After removal of all diamonds in FirDeclaration hierarchy
  FirCallableMemberDeclaration was only one inheritor of
  FirCallableDeclaration, so there is no need to keep them both
2021-07-13 10:31:20 +03:00
Dmitriy Novozhilov
adc45fd3dd [FIR] Remove useless generic parameter from deprecation utils 2021-07-13 10:31:18 +03:00
Dmitriy Novozhilov
c50fe4e399 [FIR] Move some components implementations from :entrypoint to appropriate modules 2021-07-13 10:31:17 +03:00
Alexander Udalov
173e194dac Remove dependency on JVM specifics in serialization.common
Move handling of EnhancedNullability to JVM subclasses in
serialization.jvm. Looks like this was possible because of accidental
dependency of frontend on compiler.common.jvm introduced in 564d382b9d.

Also fix a minor typo in the file name typeEnhancementUtils.kt.
2021-07-13 01:54:41 +02:00
Alexander Udalov
7a42f603f2 JVM IR: rename mangler implementation classes 2021-07-13 01:54:41 +02:00
Alexander Udalov
1e16c7d8d4 Minor, update kotlinx-metadata-jvm changelog
According to changes in 1e7295c6.
2021-07-12 22:40:02 +02:00
pyos
d988853c11 JVM_IR: optimize out redundant delegated property receiver fields
Now this:

    class C {
        val x = something
        val y by x::property
    }

is *exactly* the same as this:

    class C {
        val x = something
        val y get() = x.property
    }

(plus a `getY$delegate` method)
2021-07-12 22:38:45 +02:00
pyos
2fe7cf27ad kotlinp: use JVM_IR backend for compiling tests
Also, test optimized delegated properties.
2021-07-12 22:38:45 +02:00
pyos
791fa411d8 JVM_IR: write correct lambda invoke() signature in metadata 2021-07-12 22:38:45 +02:00
pyos
a7c13db575 JVM_IR: add $delegate methods to a few exclusion lists
1. they don't need type annotations;
 2. internal ones include the module name before the `$delegate` part,
    so further mangling is redundant
 3. they don't need multifile facade bridges.

Unlike `$annotations`, delegated properties don't appear in interfaces,
so exclusions in InterfaceLowering would be redundant.
2021-07-12 22:38:45 +02:00
pyos
6897e89bbc JVM: add tests for optimized getDelegate 2021-07-12 22:38:45 +02:00
pyos
debd58d377 JVM: use $delegate methods in KProperty[0-2].getDelegate
#KT-39055 Fixed
2021-07-12 22:38:44 +02:00
pyos
1e7295c64e JVM: add $delegate method support to kotlinx-metadata
and kotlinp as well -- it is now possible to see the effect of the
previous commit.
2021-07-12 22:38:44 +02:00
pyos
5d0102a966 JVM_IR: generate $delegate methods for val x by ::y 2021-07-12 22:38:44 +02:00
pyos
7ae4303e1b JVM_IR: slightly refactor JvmPropertiesLowering
to make it easier to generate different kinds of synthetic methods.

 #KT-47609 Fixed
2021-07-12 22:38:44 +02:00
pyos
a943cdadef JVM_IR: support generation of bound reflected property references
Not currently used though, since only references for delegated
properties' accessors are reflected, and those are unbound.
2021-07-12 22:38:43 +02:00
pyos
664bb055c8 JVM_IR: support codegen of property delegate methods
The purpose of a property-related method is now determined by its
origin; codegen no longer assumes all methods with Property metadata
source are `getX$annotations`.
2021-07-12 22:38:43 +02:00
pyos
6a3c79bb9e JVM: support on-the-fly generation of property delegates in metadata
Optimizations may remove the `x$delegate` field, in which case there
should be a `getX$delegate` method to reconstruct the value if needed
due to a call to `KProperty{0,1,2}.getDelegate`. We need to know the
signature of this method somehow.
2021-07-12 22:38:43 +02:00
pyos
e49410e07b JVM_IR: optimize delegation by property references
E.g. a statement like

    var x by ::y

is semantically equivalent to

    var x
      get() = y
      set(value) { y = value }

and thus does not need a full property reference object, or even a field
if the receiver is not bound.

 #KT-39054 Fixed
 #KT-47102 Fixed
2021-07-12 22:38:43 +02:00
Ivan Kochurkin
66e052b9b3 [FIR] Implement SPREAD_OF_NULLABLE 2021-07-12 23:16:47 +03:00
Nikita Bobko
83c5c41dd4 Fix that marketplace identifies newly uploaded Kotlin plugin artifacts as Kotlin 1.2 artifacts
This `compiler.xml` is packed into `kotlin-idea.jar` and causes troubles for marketplace
in identifying correct Kotlin plugin version
2021-07-12 22:04:20 +03:00
Mikhail Glukhikh
a997a98054 Commend -Xopt-in deprecation warning (due to bootstrap problems) 2021-07-12 21:26:21 +03:00
Mikhail Glukhikh
a92ab1bc86 Deprecate EXPERIMENTAL_IS_NOT_ENABLED diagnostic #KT-47638 Fixed 2021-07-12 21:26:20 +03:00
Mikhail Glukhikh
5871f3d663 CLI: support -option=value syntax for non-advanced flags #KT-47640 Fixed 2021-07-12 21:26:19 +03:00
Mikhail Glukhikh
d8417fd622 Introduce -opt-in stable compiler option instead of -Xopt-in
#KT-47099 Fixed
2021-07-12 21:26:18 +03:00
Mikhail Glukhikh
47c8bab48e Replace -Xuse-experimental with -Xopt-in in codebase 2021-07-12 21:26:17 +03:00
Mikhail Glukhikh
195b6d1fb1 Deprecate -Xuse-experimental #KT-47623 Fixed 2021-07-12 21:26:16 +03:00
Mikhail Glukhikh
d9531f0c61 Don't report EXPERIMENTAL_ANNOTATION_ON_WRONG_TARGET for forbidden targets
#KT-47589 Fixed
2021-07-12 21:26:15 +03:00
Ilmir Usmanov
ac7538a269 Set receivers for inline class default function stub calls
Default function stubs have dispatch and receiver parameters, but
inline class methods are static by design with receivers as ordinary
parameters. So, take these parameters and set them as receivers during
lowerings.
 #KT-46230: Fixed
2021-07-12 19:46:09 +03:00
Florian Kistner
31420a934c MI-187 Add asserts for module dependencies 2021-07-12 18:23:19 +03:00
Florian Kistner
3fe388bd17 MI-187 Also allow foreign DerivedModuleInfos, if their original module is known to the ResolverForProject 2021-07-12 18:23:17 +03:00
Mikhail Glukhikh
5f6be619c0 FIR: Don't get all*Checkers multiple times 2021-07-12 15:47:59 +03:00
Elena Lepilkina
3cabfb6a85 [K/N][New MM] Rare GC calls to optimize swiftinterop benchmarks 2021-07-12 12:27:05 +00:00
Elena Lepilkina
cdeda58ed4 [K/N][perf] Added opportunity to set up tagged branch and added benchmarks plots for new MM 2021-07-12 12:26:20 +00:00
Victor Petukhov
33a281c637 Introduce separate compiler flag for unrestricted builder inference 2021-07-12 13:57:13 +03:00
Alexander Shabalin
274dabb61d Collect stacktraces without allocating kotlin objects. 2021-07-12 08:49:33 +00:00
Alexander Shabalin
fca89c2118 Backport span from C++20
Does not support ranges and construction from arbitrary contiguous iterators as both need C++20 concepts for an adequate implementation.
2021-07-12 08:48:20 +00:00
Dmitriy Novozhilov
5efde67a0c [FIR IDE] Register java enhancement state in FirIdeSessions
This was forgotten in 6d364a5f
2021-07-12 11:47:25 +03:00
Dmitry Petrov
1f8d6d6edb JVM additional DCE tests 2021-07-12 11:09:30 +03:00
Dmitriy Novozhilov
6d364a5fee [FIR] Register enhancement state in library session too
This is needed for enhancement scopes for deserialized java declarations
2021-07-12 10:15:07 +03:00
Dmitriy Novozhilov
8e0793091a Add @NoInfer to safeAs type
This change will force specify type argument of every safeAs call
2021-07-12 10:11:36 +03:00
Dmitriy Novozhilov
ddc3ef1121 Fix all illegal usages of safeAs function
Call of `safeAs` without specifying explicit type argument is hardly
  readable and may leads to hardly detectable errors
2021-07-12 10:11:36 +03:00
Ilya Gorbunov
5072653957 Duration: parse explicit positive values parenthesized 2021-07-12 04:39:28 +00:00
Ilya Gorbunov
682cb8e34a Duration default toString: use 0, 1, 2, 3, 6, or 9 decimal digits
KT-42851
2021-07-12 04:39:27 +00:00
Ilya Gorbunov
7551719b85 Duration parsing: simplify range checks 2021-07-12 04:39:27 +00:00
Ilya Gorbunov
0427eec20f Quote invalid strings in exception messages 2021-07-12 04:39:26 +00:00
Ilya Gorbunov
3f6e2be687 Duration: do not use scientific format for large values
The largest duration value formatted in ns with maximal decimals
would fit in 40 chars.
2021-07-12 04:39:25 +00:00
Ilya Gorbunov
1be1e5279c Duration: parse and format negative values parenthesized 2021-07-12 04:39:25 +00:00
Ilya Gorbunov
ca1a9e4ca3 Duration: longer than long values in ISO components, test negative cases 2021-07-12 04:39:24 +00:00
Ilya Gorbunov
1c6ab08220 Introduce functions to parse a duration from a string KT-45325 2021-07-12 04:39:23 +00:00
Ilya Gorbunov
7ab6f6c9b2 Change Duration.INFINITE.toIsoString representation 2021-07-12 04:39:23 +00:00
Ilya Gorbunov
ae3d9cc3cd Small durations are formatted with sub-second units KT-42851 2021-07-12 04:39:22 +00:00
Ilya Gorbunov
150ce812f1 Use days component in the default duration format KT-42851 2021-07-12 04:39:21 +00:00
Ilya Gorbunov
255c4b405e Duration: round Double value to Long ns instead of truncating it KT-47675 2021-07-12 04:39:21 +00:00
Ilya Gorbunov
42cd2e65e6 Change Duration.toString format KT-42851 2021-07-12 04:39:20 +00:00
Dmitry Petrov
804db3ce91 JVM KT-47613 custom control flow analyzer for CFG builder 2021-07-11 20:16:09 +03:00
Dmitry Petrov
fe71435104 JVM KT-47613 traverse nodes backwards in backward analysis 2021-07-11 20:16:09 +03:00
Viacheslav Kormushkin
8c021af646 M1 support for cocoapods
#KT-47078
2021-07-10 19:23:51 +00:00
Ilya Gorbunov
455fee29e4 Find correct next match after matchAt and matchEntire KT-47676 2021-07-10 21:31:20 +03:00
Ilya Gorbunov
28a0698463 Regex.matchAt/matchesAt #KT-34021 2021-07-10 21:31:19 +03:00
Dmitry Petrov
d99d25e51e JVM use SPBs in fix stack analyzer 2021-07-10 19:25:25 +03:00
Dmitry Petrov
38f45d2969 JVM update licence for InstructionLivenessAnalyzer.kt 2021-07-10 19:25:24 +03:00
Dmitry Petrov
68560c60f3 JVM use FastMethodAnalyzer when possible 2021-07-10 19:25:22 +03:00
Dmitry Petrov
c54e680021 JVM FastMethodAnalyzer: prune some exception edges 2021-07-10 19:25:21 +03:00
Dmitry Petrov
07b89c6b4b JVM FastMethodAnalyzer 2021-07-10 19:25:20 +03:00
Alexander Udalov
6f72c681ed JVM IR: fix name and parent of JvmSymbols.kClassJava
In contrast to other top-level functions/properties declared in
JvmSymbols (unsafeCoerce, signatureString, etc), kClassJava refers to a
real symbol from the library. Since not all calls to it are intrinsified
(see KClassJavaProperty.kt:30), it makes sense to allow to reference it
when constructing IR. For that, it needs to have the correct file facade
as the parent, and the JvmName annotation so that its name is mapped
correctly in the codegen.

Co-authored-by: Leonid Startsev <leonid.startsev@jetbrains.com>
2021-07-10 15:33:25 +02:00
Alexander Udalov
d33debdf7c IR: minor, cleanup Symbols 2021-07-10 15:33:25 +02:00
Yahor Berdnikau
de22a467a1 Ensure default toolchain is also set to java only modules.
^KT-46972 Fixed
2021-07-09 19:36:27 +03:00
Victor Petukhov
a8e28e4b69 Update compiler tests 2021-07-09 19:21:28 +03:00
Victor Petukhov
967304ffca Don't compute default type for a fixing type variable for self type if the corresponding feature is disabled 2021-07-09 19:21:27 +03:00
Victor Petukhov
584facc95f Fix fir-related problems and tests for inferring self types 2021-07-09 19:21:25 +03:00
Victor Petukhov
9e48ef85ea Add tests for inferring self types from Java 2021-07-09 19:21:22 +03:00
Victor Petukhov
3b16865152 Don't approximate captured types while substitute them in upper bound position 2021-07-09 19:21:17 +03:00
Victor Petukhov
c2cf2f36cd Implement inferring materialized self types through a default type in ResultTypeResolver 2021-07-09 19:21:04 +03:00
Victor Petukhov
3787099a38 Put the type inference on calls with self types under the compiler flag 2021-07-09 19:20:56 +03:00
Victor Petukhov
51c5a54e31 Support type inference for self type materialization calls 2021-07-09 19:20:54 +03:00
Mikhail Zarechenskiy
44cf4be1e5 Inference for some kind of self types 2021-07-09 19:20:52 +03:00
Andrey Zinovyev
db72fd1e93 [FIR] Fix inheritance check for substitution overrides
And delegates
2021-07-09 17:14:37 +03:00
Alexander Udalov
d43ed1cf75 Minor, add test on typeOf with intersection type 2021-07-09 14:53:57 +02:00
Alexander Udalov
a7e48c3af1 Improve toString of platform types created by typeOf
In the stdlib implementation, render "!" if the type is only
nullability-flexible. Otherwise, render "($lower..$upper)".

Note that full kotlin-reflect has a much more complicated logic (see
`DescriptorRendererImpl.renderFlexibleType`) that renders things like
`(Mutable)List` and so on. It is not a goal of the stdlib implementation
to replicate all of that, since it requires copying a large amount of
code, namely the entirety of `JavaToKotlinClassMap` to map Java class
names to Kotlin.
2021-07-09 14:53:56 +02:00
Alexander Udalov
ddfa94e7e9 Support Nothing type in typeOf
The proper support will come in KT-15518, but that would be a breaking
change even for stable Kotlin without kotlin-reflect. Before that issue
is fixed, represent Nothing in types with the Void class, and use a flag
in the no-reflect implementation to remember that it's not actually the
Void class itself.

 #KT-39166 Fixed
2021-07-09 14:40:05 +02:00
Alexander Udalov
02774fae0c Report error on non-reified type parameter with recursive bound in typeOf
Instead of throwing an exception.

 #KT-40173
2021-07-09 14:31:52 +02:00
Alexander Udalov
438ce57183 Report error on typeOf<suspend ...>()
Otherwise an invalid type is constructed which causes kotlin-reflect to
crash, and stdlib implementation to render the type incorrectly. The
reason is that suspend functional types are not properly supported in
reflection. Once they are supported, this error can be removed.

 #KT-47562
2021-07-09 14:31:52 +02:00
Alexander Udalov
68432f0c20 Fix deprecation/unchecked warnings after update to 203 2021-07-09 14:24:07 +02:00
Dmitriy Novozhilov
c6f754cf7a [Build] remove dependency on IDEA classes from :visualizer 2021-07-09 14:38:03 +03:00
Dmitriy Novozhilov
aa3a73c6c2 [FIR] Move JavaTypeEnhancementState to session component 2021-07-09 14:38:02 +03:00
Simon Ogorodnik
e102bdea20 [Build] Fix xerces usage in FIR modularized tests 2021-07-09 11:08:13 +00:00
Victor Petukhov
c3a5a7754d Use proper applicability for constraint warnings
^KT-47316 Fixed
2021-07-09 14:07:01 +03:00
Victor Petukhov
1224d28deb Move java type enhancement stuff to :core:compiler.common.jvm 2021-07-09 13:22:02 +03:00
Nikita Bobko
c112e768de Update ReadMe to point to up-to-date Kotlin IDEA plugin location 2021-07-09 10:14:41 +00:00
Pavel Kunyavskiy
31857f23a3 [K/N] Refactoring: remove copypaste 2021-07-09 08:53:08 +00:00
Pavel Kunyavskiy
594ff1474d [K/N] Make llvm Int1 boolean, not byte 2021-07-09 08:53:08 +00:00
Pavel Kunyavskiy
eec8fdf16a [K/N] Implement isExperimentalMM intrinsic 2021-07-09 08:53:07 +00:00
Ilya Muradyan
55ec6729b0 [REPL] Fix completion after final expressions 2021-07-09 04:06:53 +03:00
Vyacheslav Gerasimov
a915eddf22 Build: Upgrade Idea Ext plugin to 1.0.1 2021-07-08 23:24:09 +03:00
Dmitry Petrov
24fcadb869 JVM don't run CCE on methods without optimizable conditional jumps 2021-07-08 22:11:59 +03:00
Alexander Udalov
25f0beed12 Load async-profiler.jar if possible when using -Xprofile
Instead of requiring it to be on the compiler classpath.

This will make it much easier to profile the Kotlin compiler daemon in
Gradle, by just specifying a compiler argument instead of also manually
patching the compiler jar.
2021-07-08 20:44:45 +02:00
Ilya Muradyan
787ce6335c Change nestedClasses logic to accept classes with nested type aliases
#KT-47650 fixed
2021-07-08 21:04:53 +03:00
Simon Ogorodnik
ca86b7ff7d [Build] Make getToolchainCompilerFor private and fix LibrariesCommon 2021-07-08 17:06:31 +00:00
Simon Ogorodnik
c0e479eadb [Build] Allow to override JDK 10 with JDK 11 2021-07-08 17:06:31 +00:00
Simon Ogorodnik
18eccdbc1f [Build] Allow to override JDK 9 with JDK 11 2021-07-08 17:06:30 +00:00
Simon Ogorodnik
a31bdc6454 [Build] Respect overrides in getToolchainLauncherFor 2021-07-08 17:06:29 +00:00
Simon Ogorodnik
bf25ccfc0e [Build] Allow kotlin.build.isObsoleteJdkOverrideEnabled=true on CI 2021-07-08 17:06:28 +00:00
Ilya Kirillov
eab1a78d48 FIR IDE: mute failing multimodule tests 2021-07-08 18:25:44 +03:00
Roman Golyshev
dcc30cb672 FIR IDE: Mute test with java file in the dependency
The corresponding JavaSymbolProvider currently is unable to
see the `Foo` class, because under the hood it uses
`JvmDependenciesIndexImpl` which doesn't know about the corresponding
.java file because it is created for m2-module `project`

I wasn't able to fix it yet
2021-07-08 18:25:42 +03:00
Roman Golyshev
0d443d526d FIR IDE: Use more correct implementation of TestModuleSourceInfo::dependencies
When only `regularDependencies` were used, multiplatform tests were
failing because `actual` modules did not see the `expected` ones
2021-07-08 18:25:41 +03:00
Ilya Kirillov
a9bb577154 FIR IDE: add ability to run multimodule tests 2021-07-08 18:25:39 +03:00
Andrey Zinovyev
1cb34541bd [FIR] Fixes after delegation scope rework 2021-07-08 18:13:52 +03:00
Andrey Zinovyev
02297d2c75 [FIR] Rollback exposure of j.u.List.sort method 2021-07-08 18:13:51 +03:00
Andrey Zinovyev
221e642d97 [FIR] Fix inheritance diagnostics for new FirDeclaration hierarchy
Plus several small fixes in reporting itself
2021-07-08 18:13:49 +03:00
Andrey Zinovyev
b36f8ed8f5 [FIR] DATA_CLASS_OVERRIDE_CONFLICT diagnostic 2021-07-08 18:13:48 +03:00
Andrey Zinovyev
b44785c24e [FIR] NOTHING_TO_OVERRIDE diagnostic 2021-07-08 18:13:47 +03:00
Andrey Zinovyev
9452b788bf [FIR] Implement CANNOT_OVERRIDE_INVISIBLE_MEMBER diagnostic 2021-07-08 18:13:46 +03:00
Andrey Zinovyev
f4c8108ee0 [FIR] Substitute type parameters in inheritance checker 2021-07-08 18:13:45 +03:00
Andrey Zinovyev
3f7d050f8f [FIR] Implement CONFLICTING_INHERITED_MEMBERS diagnostic 2021-07-08 18:13:44 +03:00
Andrey Zinovyev
78519f851e [FIR] Implement VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION diagnostic 2021-07-08 18:13:43 +03:00
Andrey Zinovyev
c98cd3b190 [FIR] Implement properties types mismatch on inheritence
PROPERTY_TYPE_MISMATCH_ON_INHERITANCE,
VAR_TYPE_MISMATCH_ON_INHERITANCE,
PROPERTY_TYPE_MISMATCH_BY_DELEGATION
2021-07-08 18:13:41 +03:00
Andrey Zinovyev
8c7ee0b714 [FIR] Implement RETURN_TYPE_MISMATCH_BY_DELEGATION diagnostic 2021-07-08 18:13:40 +03:00
Andrey Zinovyev
94da1e37aa [FIR] Implement RETURN_TYPE_MISMATCH_ON_INHERITANCE diagnostic 2021-07-08 18:13:38 +03:00
Konstantin Tskhovrebov
8012eb3214 Add support Apple M1 for KMP embedAndSign task.
#KT-47077
2021-07-08 16:43:59 +03:00
Hung Nguyen
a0e003ac5d Add tests for kotlin.incremental.useClasspathSnapshot feature
This ensures we don't regress when developing the feature.

Bug: KT-45777
Test: New IncrementalCompilationClasspathSnapshotJvmMultiProjectIT
      and IncrementalJavaChangeClasspathSnapshotIT
2021-07-08 15:05:38 +03:00
Dmitriy Novozhilov
d44a2f6fd3 Fix dependency on javac2.jar
In 203.8084.24 this jar was moved from intellij dependencies to
  libraries of intellij java plugin
2021-07-08 13:29:22 +03:00
Dmitriy Novozhilov
30578cfb95 Delete DynamicBundle copy
We can safely use it from IDEA after IDEA-248785 was fixed
2021-07-08 13:29:21 +03:00
Dmitriy Novozhilov
d6a6ec42a2 Use 203.8084.24 as IDEA dependency instead of 203.6682.168 2021-07-08 13:29:21 +03:00
Dmitriy Novozhilov
d473d22d8c [Test] Migrate SpecTestsConsistencyTest to JUnit5 2021-07-08 13:29:21 +03:00
Dmitriy Novozhilov
c0c9e4a114 Update testadata of PSI dump of java records 2021-07-08 13:29:21 +03:00
Dmitriy Novozhilov
955c506294 Update load java testdata with type use annotations 2021-07-08 13:29:21 +03:00
Dmitriy Novozhilov
4d4d3a998b [FIR] Update load java testdata according to new sealed modifier 2021-07-08 13:29:20 +03:00
Dmitriy Novozhilov
5552f5f5b2 [FIR] Update light classes testdata
In 203 platform java.lang.Object in position of type parameter
  bound is not rendered
2021-07-08 13:29:20 +03:00
Dmitriy Novozhilov
a710cdf822 [FIR] Properly unregister java element finder in CLI compiler 2021-07-08 13:29:20 +03:00
Dmitriy Novozhilov
817c4381f5 Fix asm version in kotlinp 2021-07-08 13:29:20 +03:00
Dmitriy Novozhilov
11faf04a4c [Test] Remove dependencies on IDEA classes from test modules
Some of IDEA services (like in `com.intellij/execution`) was copied,
  because they are used in tests but jars with them compiled with
  jdk 11 and we run our tests on jdk 8, so their bytecode can not
  be read
2021-07-08 13:29:19 +03:00
Dmitriy Novozhilov
11dfbd41ac [Test] Delete obsolete descriptor renderer tests 2021-07-08 13:29:19 +03:00
Dmitriy Novozhilov
eb94575c69 Remove redundant usages of IDEA services in CLI 2021-07-08 13:29:19 +03:00
Dmitriy Novozhilov
82e3e00bf5 Fix compilation after migrating to ASM 9 2021-07-08 13:29:19 +03:00
Yan Zhulanow
9e2fb6e25a Add verification metadata for IntelliJ 2020.3 2021-07-08 13:29:18 +03:00
Dmitriy Novozhilov
80971d7b8b ~~~~ switch 203 ~~~~ 2021-07-08 13:29:18 +03:00
Yan Zhulanow
ca8e35e7db Return 203 bunch back 2021-07-08 13:29:18 +03:00
Yan Zhulanow
cf65754ea4 Update 203 bunch 2021-07-08 13:29:18 +03:00
Dmitriy Novozhilov
ccc3e3510c [Test] Remove useless dependencies on IDEA from FIR test modules 2021-07-08 13:29:18 +03:00
Dmitriy Novozhilov
b6bc57fa09 [Test] Remove useless dependencies on IDEA from :compiler:tests-common-new 2021-07-08 13:29:17 +03:00
Dmitriy Novozhilov
88b7694762 [Test] Remove useless dependencies on IDEA from :compiler:tests-common 2021-07-08 13:29:17 +03:00
Nikita Bobko
2a26c29390 Disable kotlin-scripting-ide-common publishing
We don't need this artifact in IDE anymore since we are not
going to move ide-common classes to kotlin repo. See previous commit
2021-07-08 10:01:35 +00:00
Nikita Bobko
3ca0e11dab Add README to scripting-ide-common
Originally, we though that we would move classes from `ide-common` from Kotlin plugin to this
module but it turns that these classes are heavily used in Kotlin plugin and it's better to
keep them with the rest of Kotlin plugin. So now classes in `scripting-ide-common` are copy-pasted
2021-07-08 10:01:34 +00:00
Anton Yalyshev
e32a975814 Add change notes for 1.5.30-M1 2021-07-08 10:25:25 +03:00
Dmitry Petrov
1a0a3df9d2 JVM_IR simplify BridgeLowering
Generate bridges immediately for each class.

No need to compute existing signatures for a given method name unless it
requires a special bridge.
2021-07-07 21:24:55 +03:00
Xin Wang
8317daa00b Don't generate nullability assertions in methods for directly invoked lambdas 2021-07-07 20:32:47 +03:00
Nikita Bobko
fbe062ee64 [refactoring] Move files in scripting-ide-common into unique subpackage
I am afraid of FQN clashes with classes in `ide-common` in kotlin-ide
2021-07-07 16:51:45 +02:00
Nikita Bobko
339231b05e Move KtFunctionLiteral.findLabelAndCall from kotlin-ide.frontend-independent to compiler.psi
I want to be able to use this function in `:kotlin-scripting-ide-common` & `frontend-independent`

This commit also allows to remove copy-pasted `findLabelAndCall` in `scripting-ide-services` module
2021-07-07 16:51:44 +02:00
Dmitry Gridin
a8a6f51a0e [common] fix flexible type approximation in renders
^KTIJ-3030 Fixed

(cherry picked from commit 4855d88a9f6fbce9aeeea6fe1f29dd099a833aed)

KT-CR-2373
2021-07-07 16:51:44 +02:00
Matthew Gharrity
958b0ff24a Ignore diagnostics in ShadowedDeclarationsFilter
During code completion, ShadowedDeclarationsFilter resolves many
synthetic calls (sometimes >1000 for certain projects/scenarios).
By ignoring diagnostics we can avoid running call checkers
during this process (pending a sibling change in the compiler).

Relates to KT-44276 and github.com/JetBrains/kotlin/pull/4027
2021-07-07 16:51:44 +02:00
Matthew Gharrity
e2109c3f8f ShadowedDeclarationsFilter: check for equivalence
If there are multiple copies of the same library on the classpath,
then ShadowedDeclarationsFilter becomes very slow because it
encounters many equal-signature declarations and thus has to resolve
a lot of calls in order to pick among them.

Having multiple copies of the same library on the classpath is
somewhat common in real-world projects. It occurs in the
JetBrains/intellij-kotlin project, for example. In that project,
ShadowedDeclarationsFilter ends up resolving thousands of calls,
accounting for around 80% of completion time when there are
many completion results (see KT-44276).

We can optimize ShadowedDeclarationsFilter by checking whether the
descriptors in an equal-signature group are structurally equivalent.
If they are, we can just pick one rather than running resolve.

Testing on a small project with Kotlin stdlib duplicated on the
classpath, this change reduces overhead in ShadowedDeclarationsFilter
from 1200 ms to 20 ms when running completion on the prefix 'a'.
End-to-end completion time is cut in half.

Test: JvmBasicCompletionTestGenerated.Common.Shadowing
2021-07-07 16:51:43 +02:00
Andrei Klunnyi
decfcd28d2 KT-39398 Wrong import of unrelated object member is suggested for receiver
Receiver of a function call '<receiver>.foo()' (where receiver is a
class/object/alias name) might be specified incorrectly - corresponding
[companion] object might not be declared.

Before this commit '<receiver>' was considered to be undefined (null).
As a consequence, import suggestion included all 'foo()' functions from
the search scope.

Now as a value of '<receiver>' we set class/object/alias itself
resulting in an empty import suggestion list.
See org/jetbrains/kotlin/idea/util/CallType.kt:307
(#extractReceiverTypeFrom(descriptor: ClassDescriptor)).
2021-07-07 16:51:43 +02:00
Nikita Bobko
365821ae54 2/2 Extract code which is required for :kotlin-scripting-ide-services from ide-common into seprate module
Extract the code and keep it in Kotlin repo. See previous preparation commit as well
2021-07-07 16:51:43 +02:00
Nikita Bobko
cf3f35e1c8 1/2 Preparation commit: move ide-common files which are required for scripting to separate directory
This commit is needed to preserve git history
2021-07-07 16:51:43 +02:00
pyos
50797dba8d JVM: do not use crossinline flag when inlining assertions
Crossinline lambdas *can* be inlined into objects, but don't *have* to;
the correct place should be determined from the context, not from the
parameter.
2021-07-07 16:48:01 +02:00
pyos
e64cda61d5 JVM_IR: do not generate $assertionsDisabled twice during inlining 2021-07-07 16:48:01 +02:00
Ilya Matveev
123c76053f [Gradle][tests] Fix running CocoaPods on Apple M1 2021-07-07 17:13:34 +03:00
Ilya Matveev
5fad5e017e [Gradle][tests] Disable workaround for XCode 12.3 2021-07-07 17:13:31 +03:00
Ilya Matveev
53a4187427 [Gradle][tests] Install CocoaPods to a temp dir instead of HOME 2021-07-07 17:13:29 +03:00
Ilya Matveev
aa9ff3d6bb [Gradle][tests] Install cocoapods in MPP plugin tests 2021-07-07 17:13:26 +03:00
Svyatoslav Scherbina
2d0dbf9729 Native: improve ObjCExport thread state switching 2021-07-07 13:53:27 +00:00
Ilya Goncharov
1a27f91a98 [Gradle, JS] Remove redundant suppression 2021-07-07 16:40:22 +03:00
Ilya Goncharov
f7e69fb2ef [Gradle, JS] Update verification data with Yarn 2021-07-07 16:40:20 +03:00
Ilya Goncharov
da1bdf87cb [Gradle, JS] Use injected services of fs 2021-07-07 16:40:19 +03:00
Ilya Goncharov
e2adf9793c [Gradle, JS] Node into PATH during installing of dependencies
^KT-37895 fixed
2021-07-07 16:40:17 +03:00
Ilya Goncharov
065a5d98fb [Gradle, JS] Configuration cache friendly 2021-07-07 16:40:16 +03:00
Ilya Goncharov
81ac48390c [Gradle, JS] Make yarn working without downloading
^KT-32071 fixed
2021-07-07 16:40:15 +03:00
Ilya Goncharov
eb73527b9f [Gradle, JS] No additional checks of setup tasks 2021-07-07 16:40:13 +03:00
Ilya Goncharov
54d47de008 [Gradle, JS] Yarn as a dependency with ivy repository like Node.js
^KT-34985 fixed
2021-07-07 16:40:11 +03:00
Anton Yalyshev
1507f1a9c0 Add change notes for 1.5.21 2021-07-07 16:30:34 +03:00
Andrey Zinovyev
de3f31cf78 [FIR] Partial implementation of DEPRECATION(_ERROR) diagnostics
No support for inheritance deprecations
and deprecations in qualifier's parts
2021-07-07 16:19:28 +03:00
Andrey Zinovyev
9fad55d551 [FIR] Use @DeprecatedSinceKotlin in the resolution 2021-07-07 16:19:27 +03:00
Igor Yakovlev
b64f7909b8 [FIR IDE] Implement own fir light classes support 2021-07-07 14:08:41 +02:00
Yahor Berdnikau
7fff282565 Fix AllOpen plugin exposes common with Gradle runtime dependencies.
^KT-47354 Fixed
2021-07-07 11:31:18 +00:00
Mikhail Glukhikh
fa086d22c2 Don't build kotlin-gradle-statistics in FIR mode at all 2021-07-07 14:28:03 +03:00
Mikhail Glukhikh
863a2c6498 Disable kotlin-gradle-statistics and wasm.ir under FIR 2021-07-07 14:28:02 +03:00
Mikhail Glukhikh
c7877cb440 FIR: fix contract deserialization for assertIs<T> 2021-07-07 14:28:00 +03:00
Ilya Goncharov
e0c1f50f03 [Gradle, JS] Fix node.js repository declaration
^KT-47557 fixed
2021-07-07 08:26:07 +00:00
Sergey Bogolepov
f05110f99b [K/N] Add some tests for https://youtrack.jetbrains.com/issue/KT-47605 2021-07-07 07:50:57 +00:00
Sergey Bogolepov
9ed97a27f1 [K/N] Introduce LLD compatibility checker for MinGW
We are going to switch to LLD linker for MinGW targets.
Right now LLD for MinGW doesn't support all features
of ld.bfd and thus this change might be breaking for some users.
To make transition smoother, we run lld -### to show a warning to user
so they can update their compilation options before LLD will be turned
on by default.

More details: https://youtrack.jetbrains.com/issue/KT-47605
2021-07-07 07:50:57 +00:00
Ilya Kirillov
30d0fea003 FIR IDE: enable explicit API mode in idea-frontend-fir module 2021-07-07 01:40:03 +03:00
Ilya Kirillov
51576c70b6 FIR: introduce package directive
The package directive is needed for KtElement -> FirElement mapping in IDE.
There should be some FirElement which will be result of mapping of elements
inside KtPackageDirective.
2021-07-06 22:49:50 +03:00
Mikhail Glukhikh
bf40c07cc3 FIR: drop questionable DiagnosticKind.NotRootCause 2021-07-06 18:43:16 +03:00
Mikhail Glukhikh
7d583973ab Disable -Werror in FIR mode inside disableDeprecatedJvmTargetWarning 2021-07-06 18:27:53 +03:00
Tianyu Geng
768ddea18f FIR checker: ILLEGAL_DECLARATION_IN_WHEN_SUBJECT 2021-07-06 18:27:47 +03:00
Tianyu Geng
31573a98e8 FIR checker: report EXPECTED_CONDITION 2021-07-06 18:27:23 +03:00
Sergey Bogolepov
e396da0562 [K/N] Update list of targets with stable caches
Enable compiler caches for iosSimulatorArm64 and macosArm64 targets
to make Apple Silicon distribution feature complete with
Intel-based one.
2021-07-06 18:15:30 +03:00
Victor Petukhov
65fd8fc174 Add generated files with descriptors for foreign annotation tests 2021-07-06 18:10:22 +03:00
Ilya Goncharov
c797d38312 [Gradle, JS]Add base dirs and prefix for correct source maps calculating 2021-07-06 12:59:03 +00:00
Alexander Udalov
e7b37d99cb Fix new compiler warnings in daemon and build-common 2021-07-06 13:31:21 +02:00
Sergey Shanshin
0d211a53cb Support serializable classes clash with JVM primitive types by name
Fixes Kotlin/kotlinx.serialization#1353
2021-07-06 12:52:53 +03:00
Ilya Goncharov
7181631051 [Gradle, JS] Add statistics for Kotlin/JS
- source map usages (legacy, ir)
- incremental klib
- incremental JS IR
- property lazy initialization

^KT-47435 fixed
2021-07-06 07:38:56 +00:00
Victor Petukhov
6cfb1f40d6 Specify jspecify mode explicitly for warnings in tests 2021-07-06 09:54:32 +03:00
Victor Petukhov
74aa8e7497 Get rid of singleOrNull of NullabilityAnnotationStates 2021-07-06 09:54:31 +03:00
Victor Petukhov
877ca370c2 Use memoized function to compute and store annotation states cache 2021-07-06 09:54:31 +03:00
Victor Petukhov
50ad5116b5 Add CLI test for -Xnullability-annotations 2021-07-06 09:54:30 +03:00
Victor Petukhov
b0a44705b4 Take into account user defined jsr-305 annotations 2021-07-06 09:54:30 +03:00
Victor Petukhov
b2dff10e32 Implement caching states for nullability annotations 2021-07-06 09:54:30 +03:00
Victor Petukhov
a82772f31a Depend on passed language version explicitly to compute nullability annotation settings 2021-07-06 09:54:29 +03:00
Victor Petukhov
18384788a4 Move type enhancement state stuff into core:descriptors.jvm 2021-07-06 09:54:29 +03:00
Victor Petukhov
8de05691a9 Revert "Move fqname related stuff into core:util.runtime module"
This reverts commit e651e1c6
2021-07-06 09:54:28 +03:00
Victor Petukhov
ea901d81fb Get rid of redundant Jsr305State 2021-07-06 09:54:28 +03:00
Victor Petukhov
f46dc713d7 Support rxjava 3 nullability annotations 2021-07-06 09:54:28 +03:00
Victor Petukhov
6d3badb2cd Support configuring of nullability annotations with their report levels through a test directive 2021-07-06 09:54:27 +03:00
Victor Petukhov
61c2f1b203 Extract building JSR-305 settings to separate function 2021-07-06 09:54:27 +03:00
Victor Petukhov
f92ab691f8 Add explicit enabling of TypeEnhancementImprovementsInStrictMode in jspecify tests 2021-07-06 09:54:26 +03:00
Victor Petukhov
39ffcd3ba6 User proper report level for compatqual nullability annotations 2021-07-06 09:54:26 +03:00
Victor Petukhov
e16033f8d8 Add androidx recently nullability annotations 2021-07-06 09:54:26 +03:00
Victor Petukhov
d5180f79aa Support picking settings of exacter annotations by the length of the matching part of fqname 2021-07-06 09:54:25 +03:00
Victor Petukhov
70dbc50305 Rename JSPECIFY_DEFAULT_NOT_NULL to JSPECIFY_NULL_MARKED 2021-07-06 09:54:25 +03:00
Victor Petukhov
4173f2d294 Don't forget jspecify annotation during extracting nullability from known annotations 2021-07-06 09:54:24 +03:00
Victor Petukhov
46d0b16142 Use new default settings for java nullability annotations in JavaTypeEnhancementState and get rid of all hardcoded defaults 2021-07-06 09:54:24 +03:00
Victor Petukhov
8e7c0e8c61 Describe default settings for java nullability annotations depending on current kotlin version 2021-07-06 09:54:24 +03:00
Victor Petukhov
205087cae3 Move fqname related stuff into core:util.runtime module 2021-07-06 09:54:23 +03:00
Victor Petukhov
c8af1b735f Introduce compiler flag to manage status of specific Java nullability annotations 2021-07-06 09:54:23 +03:00
Yahor Berdnikau
c3a3e99724 Fix toolchain is not applied for modules with 'java' plugin.
Use common base java plugin for configuration action: 'java-base'.

^KT-46972 Fixed
2021-07-05 23:15:44 +02:00
Alexander Udalov
113632c49c Psi2ir: load single-value Java array annotation arguments correctly
#KT-47467 Fixed
2021-07-05 21:49:10 +02:00
Pavel Punegov
269f83f86e Update kotlin-build-gradle-plugin to 0.0.31 2021-07-05 19:43:28 +00:00
Pavel Punegov
c2fe46020e Native: improve CompilerVersion to correspond to the versioning schema
* Add pub and dev-google-pr meta versions
* Allow using release versions with and without build number
* Add tests for version parsing
2021-07-05 19:43:27 +00:00
Yahor Berdnikau
1bd0607b53 Fix toolchain jdk override was not working for all modules.
Now it also considers the case when separate tasks toolchain
are configured or module only has java toolchain.

^KT-46972 Fixed
2021-07-05 21:15:04 +02:00
Pavel Kunyavskiy
70ca222806 [K/N] Disable external calls checker for wasm target 2021-07-05 18:49:09 +00:00
Zalim Bashorov
4c4bcb1e3e [Gradle, JS] Turn on by default sourcemap generation for JS IR
#KT-46551 Fixed
2021-07-05 21:01:45 +03:00
Zalim Bashorov
8da62b56fb [IR] Put correct line numbers on return while inlining
#KT-46551 In Progress
2021-07-05 21:01:44 +03:00
Zalim Bashorov
d1f5ab4b09 [JS IR] Generate correct source locations in sourcemap for inline declarations
* Keep returnable blocks.
* Add a new lowering which simplifies returnable blocks by introducing
  temporary variable for result and changing returnable block's type to Unit.
* Use information from returnable blocks in codegen to generate
  the right source locations in sourcemap.
* Support in namer (LocalNameGenerator).
* Fix some lowerings to work correctly with returnable blocks.

#KT-46551 In Progress
2021-07-05 21:01:43 +03:00
Zalim Bashorov
2460f5f9ae [JS CLI] Support sourcemap generation for IR BE in CLI
#KT-46551 In Progress
2021-07-05 21:01:41 +03:00
Zalim Bashorov
5a3efc1a98 [JS IR] Fill source info in codegen
#KT-46551 In Progress
2021-07-05 21:01:40 +03:00
Zalim Bashorov
64c6d852de [JS IR] Preparing for introducing sourcemap as another compilation output
* Rename `JsCode` to `CompilationOutputs`.
* Rename members of CompilerResult.

#KT-46551 In Progress
2021-07-05 21:01:38 +03:00
Zalim Bashorov
d9b7230144 [JS IR] add dependency to sourcmap module
#KT-46551 In Progress
2021-07-05 21:01:37 +03:00
Zalim Bashorov
aae1057f35 [IR] Support IrReturnableBlock inside IR renderer 2021-07-05 21:01:35 +03:00
Ilya Chernikov
6911860cca Clean-up coroutines usage in scripting libs and plugin
#KT-30778 fixed (again)
2021-07-05 19:26:42 +03:00
Ilya Chernikov
49e0b639f8 Add JSR-223 tests with compilable and bindings 2021-07-05 19:26:40 +03:00
Ilya Chernikov
32b6cfe2ea [Scripting] fix receiver substitution in script JVM IR lowering 2021-07-05 19:26:39 +03:00
Ilya Chernikov
a7b94b398a [minor] Bump serialization lib version in scripting test 2021-07-05 19:26:38 +03:00
Ilya Chernikov
0c2591e938 Bump coroutines version used in scripting to 1.5.0
#KT-43917 fixed
2021-07-05 19:26:37 +03:00
Igor Yakovlev
64afba299f [imltogradle] Don't use deprecated kotlinOptions.jdkHome in generated build.gradle.kts files 2021-07-05 17:52:04 +02:00
Tianyu Geng
4c439bb5d7 FIR: fix DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR
DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR should be an error but it's
somehow a warning in FIR.
2021-07-05 18:32:37 +03:00
Tianyu Geng
db1db6c64c FIR: fix CYCLIC_CONSTRUCTOR_DELEGATION_CALL
Somehow it's a warning in FIR, but it should be an error.
2021-07-05 18:32:36 +03:00
Jinseong Jeon
cd78a156c5 FIR checker: apply member checkers to anonymous objects
because they can have member properties/functions too.
2021-07-05 18:32:34 +03:00
Jinseong Jeon
64a275cf83 FIR: fix type comparator
As many other places did, this one is supposed to return the diff value
if the given two intersection types' sizes are different.
2021-07-05 18:32:33 +03:00
Tianyu Geng
cdfb2fb3d9 FIR checker: report SETTER_PROJECTED_OUT 2021-07-05 18:32:32 +03:00
pyos
c3a91efea3 JVM_IR: fix primitive comparison optimizations
1. the `primitive == object?.something` fusion should not apply to
    `primitive.equals(object?.something)` because it can't;

 2. coercions to Int are there for a reason - don't remove them;

 3. better optimize `primitive == object?.something` -- the result
    should be subject to if-null fusion, so it needs to have a specific
    pattern that resembles safe calls.

 #KT-47597 Fixed
2021-07-05 18:13:09 +03:00
Yahor Berdnikau
7e70c93cbf Allow to avoid using JDK 1.6 and JDK 1.7 in the repo.
This behaviour could be enabled via adding
'kotlin.build.isObsoleteJdkOverrideEnabled=true'
to the 'local.properties' file.

^KT-46972 Fixed
2021-07-05 14:11:13 +00:00
Yahor Berdnikau
7789054547 Migrate repo to use JVM toolchains Gradle feature.
^KT-46972 Fixed
2021-07-05 14:11:12 +00:00
Yahor Berdnikau
08d831934a Revert "Build: add temporary option to suppress jdkHome warning"
This reverts commit 1dfcec3a93.
2021-07-05 14:11:11 +00:00
sebastian.sellmair
5b5dddc2d1 [Commonizer] Restore TypeAliasCommonizer's Commutative property & TypeAliasTypeCommonizer: substitute underlying-type arguments
^KT-47574 The fix done here supports only one level of substituting
underlying type-arguments.

HierarchicalTypeAliasCommonizationTest.`KT-47574 - test long typealias chain`
will assert proper behaviour for nested chains.
2021-07-05 09:00:46 +00:00
sebastian.sellmair
448302d19b [Commonizer] CommonizeNativeDistributionTest.commonize - apple platforms(): Require macos 2021-07-05 09:00:45 +00:00
sebastian.sellmair
1e801e77a2 [Commonizer] HierarchicalClassAndTypeAliasCommonizationTest: Remove unnecessary annotations and reformat file 2021-07-05 09:00:44 +00:00
sebastian.sellmair
684e51b0be [Commonizer] Implement TypeCommonizer as AssociativeCommonizer 2021-07-05 09:00:44 +00:00
sebastian.sellmair
b29fd17d26 [Commonizer] Use AssociativeCommonizer signature to implement ClassOrTypeAliasTypeCommonizer
This drastically improves performance for now, since the previous
Adapter implementation was at least O(n^2). While the Adapter
implementation could have been reduced to O(n), the Signature of
StatelessCommonizer was misleading.

StatelessCommonizer will be introduced back later when other
Commonizer implementations are ready to be converted to a new
Signature.
2021-07-05 09:00:43 +00:00
sebastian.sellmair
20f55ef0b7 [Commonizer] Commonize 'const val' and 'val' properties 2021-07-05 09:00:42 +00:00
sebastian.sellmair
9794068f22 [Commonizer] typeAliasUtils: computeSuitableUnderlyingType: Consider commonized type-aliases 2021-07-05 09:00:42 +00:00
sebastian.sellmair
5ca81b01f0 [Commonizer] Improve AbstractCommonizerTest diagnostic message 2021-07-05 09:00:41 +00:00
sebastian.sellmair
d7022cb378 [Commonizer] Move ClassTypeCommonizer and TypeAliasTypeCommonizer into seperate files 2021-07-05 09:00:40 +00:00
sebastian.sellmair
8f73df0f85 [Commonizer] Implement new ClassOrTypeAliasTypeCommonizer
^KT-47432 Verification Pending
^KT-47434 Verification Pending
2021-07-05 09:00:39 +00:00
sebastian.sellmair
8e2780345c [Commonizer] HierarchicalClassAndTypeAliasCommonizationTest: Un-ignore tests fore ^KT-47432 and ^KT-47434 and add additional test's 2021-07-05 09:00:39 +00:00
Pavel Kunyavskiy
fc75486611 [K/N] Debug tool for checking state at call points of unknown functions
After linking runtime, llvm-ir is modified to add checker function
call at all points where unknown function, which can possibly run long
is called. This function checks Native state is set, to avoid long locks
at gc.
2021-07-05 08:35:23 +00:00
Pavel Kunyavskiy
1ba04fdd21 [K/N] Introduce external calls checker compiler option 2021-07-05 08:35:23 +00:00
Pavel Kunyavskiy
271fc35082 [K/N] Minor debug info fix 2021-07-05 08:35:22 +00:00
Pavel Kunyavskiy
4c2d518cf5 [K/N] Move ClearCurrentThreadData() out of TestSupport 2021-07-05 08:35:21 +00:00
Pavel Kunyavskiy
65bebd3058 [K/N] Support AddressToSymbol using dladdr, if availible 2021-07-05 08:35:20 +00:00
Pavel Kunyavskiy
b7707d8755 [K/N] Introduce api for getting existing global by name from StaticData 2021-07-05 08:35:20 +00:00
Pavel Kunyavskiy
1db2903e4f [K/N] Add utilities to check if thread is registered now 2021-07-05 08:35:19 +00:00
Vyacheslav Gerasimov
aff9d96e8a Build: Update gradle enterprise and test distribution plugins 2021-07-04 18:15:36 +03:00
Dmitriy Novozhilov
6e1fce6b8b [FIR] Fix creating scopes for enum entry initializers
Before we analyzed initializers of enum entry with scope for constructor
  in implict type mode, so scope was untouchable. Now we analyze them
  in body resolve phase, so previously we add value parameters to
  constructors scope, which mess up scope of enum entry initializer
2021-07-04 13:29:03 +03:00
Dmitriy Novozhilov
1593c4859d [FIR] Get rid of all conditional reads of FirDeclaration.resolvePhase 2021-07-04 13:29:03 +03:00
Dmitriy Novozhilov
43fe0c3bc1 [FIR] Don't initialize type of FirAnonymousObjectExpression
In some cases we check that some declaration (e.g. field) was
  analyzed by checking type of it's body/initializer (is it implicit
  or not), so if type of FirAnonymousObjectExpression is not implicit
  we can skip resolve of anonymous object itself
2021-07-04 11:17:50 +03:00
Dmitriy Novozhilov
32173a408a [FIR] Update type of getter after approximation of property type 2021-07-04 11:17:49 +03:00
Roman Artemev
d472b6c71c [Psi2Ir] Replace custom IrProperty node with common one 2021-07-02 19:58:31 +03:00
Roman Artemev
4d5186d332 [Psi2Ir] Untangle psi2ir from frontend.java
Add extension method to detect and unwrap `JavaSyntheticProperty`
2021-07-02 19:58:30 +03:00
Dmitriy Novozhilov
3f5e6a79c7 Replace all throw error(...) with just error(...)
`throw` is not needed in this case, because `error(...)` already
  raises exception (so `throw` is unreachable). Also after previous
  commit compiler reports `UNREACHABLE_CODE` warning on such `throw`
2021-07-02 17:55:21 +03:00
Dmitriy Novozhilov
ae608ea67f [FE 1.0] Always create return value for CallInstruction
This fixes missing `USED_AS_EXPRESSION` recordings
^KT-47527 Fixed
2021-07-02 17:55:20 +03:00
bracadabra
b2372ff0b9 Fix UTFDataFormatException on encoding long subplugin options.
ObjectOutputStream.writeUTF(String) has an unsigned short limit on
String length. On Projects with deep nested modules subplugin
options could produce String over this limit.

^KT-45202 Fixed
2021-07-02 16:17:54 +02:00
Simon Ogorodnik
f8ab16c823 [Build] Fix useFir project exclusion logic 2021-07-02 16:13:05 +03:00
Dmitriy Novozhilov
f7c68afb18 [FIR] Don't report EXPOSED_FUNCTION_RETURN_TYPE on property accessors 2021-07-02 15:55:12 +03:00
Dmitriy Novozhilov
3a34a2ca62 [FIR] Properly infer published effective visibility for member declarations 2021-07-02 15:55:10 +03:00
Dmitriy Novozhilov
f1bf3c0d5a [FIR] Don't duplicate annotations from enum entry to its initializer 2021-07-02 15:55:09 +03:00
Dmitriy Novozhilov
9f547171da [FIR] Properly calculate annotation targets for enum entries 2021-07-02 15:55:08 +03:00
Dmitriy Novozhilov
7baea7244a [FIR] Don't report VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION on lambda parameters 2021-07-02 15:55:07 +03:00
Dmitriy Novozhilov
0ab4770f02 [FIR] Add correctly reported diagnostics to testdata 2021-07-02 15:55:05 +03:00
Dmitriy Novozhilov
1f1065d858 [FIR] Add specific checkers for each leaf expression type 2021-07-02 15:55:04 +03:00
Dmitriy Novozhilov
d3ba821371 [FIR] Add specific checkers for each leaf declaration type 2021-07-02 15:55:02 +03:00
Dmitriy Novozhilov
2446ad9510 Advance bootstrap to 1.6.0-dev-328 2021-07-02 15:46:20 +03:00
Igor Laevsky
ce6459d059 WASM: Optimize few cases where spread operator is used on an immediate array 2021-07-02 15:39:30 +03:00
Igor Laevsky
d835b3c164 WASM: Implement spread operator 2021-07-02 15:39:29 +03:00
Igor Laevsky
f5e59194b5 WASM: Fix linker issues around fake overrides 2021-07-02 15:39:28 +03:00
Igor Laevsky
74a87e2b79 WASM: Add few helper array library functions from Slava's changes 2021-07-02 15:39:26 +03:00
Ilya Matveev
dc8186cb83 [K/N][Interop] Fix throwing exceptions through bridges in opt mode
By default, C functions compiled to bitcode by clang have the
nounwind attribute. If such functions throws an exception, the
behaviour is undefined.

Our interop machinery can process foreign exceptions on call sites
(terminate or wrap them in Kotlin exceptions). But if the interop
bridges have the nounwind attribute, LLVM optimizations (particularly
inlining) may lead to the situation when a foreign exception is ignored by
our foreign exception handler.

This patch fixes the issue by compiling bridges with -fexceptions flag.
This flag makes clang to not set the nounwind attribute, so exceptions
can be thrown through C frames.
2021-07-02 11:51:06 +00:00
Dmitry Petrov
c132e1a39f PSI2IR fix flaky SOE 2021-07-02 13:10:04 +03:00
Roman Golyshev
7b1052296e Do not try to create a light class for classes in unexpected positions
Example of such class declaration would be `10 < class A` expression

The expression is uncompilable, but parsable. Unfortunately, the
FIR compiler does not save `class A` reference in it (because it
is not an expression, and only an expression can be a LHS or RHS of
binary expression `10 < ...`)

When we try to build light classes, we will try to find/build FIR
declaration for this class, but we won't be able to, and this will throw
an error

Adding this check should fix few
`FirKotlinHighlightingPassTestGenerated$Regression` tests
2021-07-02 04:07:26 +03:00
Dmitry Petrov
584310615c JVM_IR KT-47499 use proper signature for 'clone' intrinsic 2021-07-01 22:10:47 +03:00
Alexander Udalov
e2f462095d IR: move JVM-specific flexible types to backend.jvm 2021-07-01 19:35:46 +02:00
Alexander Udalov
2834c22a85 IR: add BackendContext.typeSystem and JvmIrTypeSystemContext
To be able to override JVM-specific behavior of IrTypeSystemContext in
JVM IR, for things like JVM flexible types.
2021-07-01 19:35:44 +02:00
Alexander Udalov
ae07127f08 JVM IR: support raw types in typeOf 2021-07-01 19:33:56 +02:00
Alexander Udalov
012c7c39af Improve KType.toString for primitive type arguments in stdlib implementation 2021-07-01 19:33:55 +02:00
Alexander Udalov
7306256127 JVM IR: support mutability-flexible types 2021-07-01 19:33:55 +02:00
Alexander Udalov
0cb905a4b1 Support mutable collection types in typeOf
flexibleTypes_1_6.kt is fixed for JVM IR in a subsequent commit.

 #KT-35877 Fixed
2021-07-01 19:33:55 +02:00
Alexander Udalov
6e975b3498 Support flexible types internally in typeOf
#KT-45066 Fixed
2021-07-01 19:33:55 +02:00
Alexander Udalov
26cdb2f928 Reformat reflection.jvm, fix inspections 2021-07-01 19:33:54 +02:00
Yahor Berdnikau
a44e82a1d9 Fix publication failed in projects which are using BOM.
^KT-47444 Fixed
2021-07-01 15:14:35 +00:00
Denis.Zharkov
6e763f5a61 Minor. Add review fixes
Didn't squash them because there are file-moving-renaming commits above
2021-07-01 17:49:40 +03:00
Denis.Zharkov
a3f64f65f2 FIR: Fix serialization of non-delegated members in FirDelegatedMemberScope 2021-07-01 17:49:39 +03:00
Denis.Zharkov
3671b14e5b FIR: Fix compilation after rebase 2021-07-01 17:49:38 +03:00
Denis.Zharkov
44113f8501 FIR: Get rid of hacks related to previous structure of FirDelegatedScope
^KT-47413 Fixed
2021-07-01 17:49:36 +03:00
Denis.Zharkov
8a3a7a1ab5 FIR: Rename FirNewDelegatedMemberScope 2021-07-01 17:49:34 +03:00
Denis.Zharkov
4d28b9ea3b FIR: Remove FirDelegatedMemberScope 2021-07-01 17:49:32 +03:00
Denis.Zharkov
a77cbb8f63 FIR: Rework FirNotImplementedOverrideChecker around delegated members reporting 2021-07-01 17:49:30 +03:00
Denis.Zharkov
a213ee0e01 FIR: Rework delegated scope
Now delegated members are generated just to declared scope

^KT-47413 In Progress
2021-07-01 17:49:29 +03:00
Denis.Zharkov
082dc3332e FIR2IR: Move util methods closer to the single usage 2021-07-01 17:49:27 +03:00
Roman Artemev
9ef0909e39 Advance K/N version to make Gradle Klib IT tests work 2021-07-01 17:40:47 +03:00
Roman Artemev
7ef63fbb45 [Psi2Ir] Isolate type translator in file scope
Create TypeTranslator per file to avoid reusing it between files
2021-07-01 17:40:46 +03:00
Roman Artemev
ae3a2d4e71 Use DescriptorVisibilities.isPrivate instead of simple equality 2021-07-01 17:40:44 +03:00
Roman Artemev
55793d078c [KLIB] Fix Mangler Checker to work with new signatures 2021-07-01 17:40:43 +03:00
Roman Artemev
09d30c91bf [JS TESTS] Disable mangler checker in tests 2021-07-01 17:40:41 +03:00
Roman Artemev
a8d0e60328 [JS TESTS] Extend test frame with some features
- Setting up specific ABI version for module
- Disabling mangle verification
2021-07-01 17:40:40 +03:00
Roman Artemev
3403c464fe [KLIB] Promote library ABI version 2021-07-01 17:40:39 +03:00
Roman Artemev
b8e5185b61 [KLIB] Add extra debug information for Local signatures 2021-07-01 17:40:37 +03:00
Roman Artemev
b5c28c1912 [KLIB] Introduce compatible mode for klibs.
Based on library ABI version linker could decide which signature mode
to be used to guarantee backward compatibility.
2021-07-01 17:40:36 +03:00
Roman Artemev
3e99951a66 [Psi2Ir] Fix IrText testdata 2021-07-01 17:40:33 +03:00
Roman Artemev
6cdac22a23 [IR] Introduce new IdSignatures
FileSignature, CompositeSignature, LocalSignature

They are needed to make possible reference any non-local declaration via
 signature, including private signature, type parameters and so on.

- Support those new signatures in proto and klibs
- Rename `isPublic` -> `isPubliclyVisible` due to changed semantic
- Fix FIR
- clean up code
2021-07-01 17:40:31 +03:00
Roman Artemev
7139785036 [KLIB] Rename proto PublicIdSignature -> CommonIdSignature 2021-07-01 17:40:30 +03:00
Roman Artemev
0856cd82d7 [IR] Rename PublicSignature -> CommonSignature 2021-07-01 17:40:28 +03:00
Roman Artemev
5a284de2d4 add tests for private signatures
regenerate tests

add test for EnumEntry's argument declarations

add another test

regenerate test

fix test a bit
2021-07-01 17:40:27 +03:00
Svyatoslav Scherbina
2865d8bd45 Deprecate Obj-C 'alloc' and 'allocWithZone:' methods in Kotlin
Using these methods in Kotlin is usually a mistake.
2021-07-01 12:20:24 +00:00
Ilya Matveev
e5aa7e1625 [K/N] Disable some tests for noop GC 2021-07-01 10:05:02 +00:00
Alexander Shabalin
c286a9d8c6 Extract StackTrace from Exceptions 2021-07-01 07:23:47 +00:00
Roman Golyshev
bd0f48e07a Add rendering for FirValueParameter in DECLARATION_NAME renderer
Without it NAME renderer renders parameters as '???'
2021-06-30 19:35:33 +03:00
Ivan Kylchik
c176d4d7b0 Rename createTempDirectory to getOrCreateTempDirectory
With cache this function can be used to get already created directory
by name.
2021-06-30 19:33:17 +03:00
Ivan Kylchik
88aa71b0aa Add possibility to dump and test IR after execution of given lowering 2021-06-30 19:33:15 +03:00
Ilya Kirillov
330f15ff7d Add uast-kotlin-idea-fir module to the list of ide modules 2021-06-30 16:38:31 +02:00
Konstantin Tskhovrebov
b45140d237 Update default K/N ios test simulator to "iPhone 12".
#KT-45416
2021-06-30 14:19:53 +00:00
Pavel Kunyavskiy
b2f0e0e0d3 Revert "Native: exclude tests that fail due to the KT-47405 and KT-47408"
This reverts commit 6ae6209031.
2021-06-30 13:47:28 +00:00
Pavel Kunyavskiy
abf6ae70e2 [K/N] Add workaround options to arm64 targets 2021-06-30 13:47:28 +00:00
Dmitry Petrov
37b05cd9c2 JVM_IR KT-47120 treat outer name as case-insensitive for local classes 2021-06-30 14:04:22 +03:00
Andrey Zinovyev
1130344fb1 [lombok] Get field names directly from JavaClassImpl
Otherwise it fails with recursion on annotation types
#KT-47513 Fixed
2021-06-30 10:44:31 +03:00
Ivan Kochurkin
9b71175902 [FIR] Get rid of unnecessary creation of error expression for LightTree, other minor simplifications 2021-06-29 22:39:24 +03:00
Ivan Kochurkin
9f7a8c3948 [FIR] Implement ILLEGAL_SELECTOR 2021-06-29 22:39:23 +03:00
Ivan Kochurkin
a7276b25ae [FIR] Add expression field to FirErrorExpression
It is used to report diagnostics even in erroneous code (within ILLEGAL_SELECTOR for instance).
2021-06-29 22:39:22 +03:00
Ivan Kochurkin
59257e47c9 [FIR] Implement FUNCTION_CALL_EXPECTED 2021-06-29 22:39:22 +03:00
Dmitriy Novozhilov
d048bccfa2 Build: fix detecting .iml files for kotlin-ide development 2021-06-29 21:03:31 +03:00
Dmitriy Novozhilov
5816d7ae9f [FIR] Rename FirStatusOwner back to FirMemberDeclaration 2021-06-29 21:03:30 +03:00
Dmitriy Novozhilov
f400477c70 [FIR] Remove generic parameter from FirDeclaration 2021-06-29 21:03:30 +03:00
Dmitriy Novozhilov
511e564b20 [FIR] Add specific symbols for value parameters and enum entries
Make FirVariableSymbol a sealed class
2021-06-29 21:03:30 +03:00
Dmitriy Novozhilov
62d781a70f [FIR] Move delegateFieldSymbol from FirVariable to FirProperty 2021-06-29 21:03:30 +03:00
Dmitriy Novozhilov
dc3ee6318c [FIR] Rename type parameters of NullableMap from KEY, VALUE to K, V 2021-06-29 21:03:30 +03:00
Dmitriy Novozhilov
6c8096643c [FIR] Move danglingConstraints attribute to other attributes 2021-06-29 21:03:30 +03:00
Dmitriy Novozhilov
eca77324e0 [FIR] Move declaration comparators to separate package 2021-06-29 21:03:29 +03:00
Dmitriy Novozhilov
725be466f0 [FIR] Move declaration utils to separate package 2021-06-29 21:03:29 +03:00
Dmitriy Novozhilov
10ff0975bc [FIR] Split FirDeclarationUtil.kt to multiple files 2021-06-29 21:03:29 +03:00
Dmitriy Novozhilov
4225813d79 [FIR] Update CFG dumps according to changed order of visiting class children 2021-06-29 21:03:29 +03:00
Dmitriy Novozhilov
1324e9223f [FIR] Make FirDeclaration an abstract class 2021-06-29 21:03:28 +03:00
Dmitriy Novozhilov
b3e5c6e079 [FIR] Add symbol to all declarations. Get rid of FirSymbolOwner 2021-06-29 21:03:28 +03:00
Dmitriy Novozhilov
39cd1c8504 [FIR] Squash AbstractFirBasedSymbol with FirBasedSymbol 2021-06-29 21:03:28 +03:00
Dmitriy Novozhilov
823cbc59b7 [FIR] Split FirAnonymousFunction to expression and declaration 2021-06-29 21:03:28 +03:00
Dmitriy Novozhilov
85b844c748 [FIR] Split FirAnonymousObject to expression and declaration 2021-06-29 21:03:27 +03:00
Victor Petukhov
ad89d43186 Prevent recursion on captured recursive type parameters of inner classes during computing bound for them
^KT-47459 Fixed
2021-06-29 20:53:54 +03:00
Victor Petukhov
e071281b20 Prevent recursion on erasion of raw types with interdependent type parameters
^KT-47480 Fixed
2021-06-29 20:53:52 +03:00
Jiaxiang Chen
0774d4d734 expose original message collector in CLIConfiguration 2021-06-29 19:01:09 +03:00
Simon Ogorodnik
54c914e3fd [Build] Update NodeJs to 16.2.0 2021-06-29 18:35:13 +03:00
Simon Ogorodnik
021d053cfe [Gradle, JS] Fix architecture detection for M1 in NodeJsPlatform 2021-06-29 18:35:11 +03:00
Dmitry Petrov
68c3f30aa7 JVM_IR KT-47510 indy callee parent is a package fragment, not a class 2021-06-29 17:00:31 +03:00
Konstantin Tskhovrebov
a54e758189 For XCFramework with default name register 'nameless' task 'assembleXCFramework`
#KT-42667
2021-06-29 13:11:14 +00:00
Ivan Gavrilovic
08c505f9ba KT-47347: Kapt processors should not be input files for stub generation
This commit avoids passing kapt processors as sources for stub generation
task, and it also avoid using them as input files for stub generation.
Instead, it adds a new property that simply records if processors are
present (as going from empty to 1+ processors should re-run stubs).

Fixes #KT-47347

Test: Kapt3IT.kt
2021-06-29 15:11:29 +03:00
Aleksei.Cherepanov
d564bfd450 Fix visibility for JPS build 2021-06-29 14:36:50 +03:00
max-kammerer
71d59f89cb Fix type 2021-06-29 12:54:43 +02:00
Andrei Klunnyi
72d188efd9 Update contributing guide
After Kotlin-IDE-plugin is moved to intellij repository, this commit
updates contributing.md guide with corresponding references.
Other than that brief information on current repository is provided.
2021-06-29 10:46:29 +00:00
Ilya Goncharov
b678cc3c90 [JS IR] Fast return in boolean externals lowering
- Put fqname when available instead of just name
2021-06-29 10:12:56 +00:00
Ilya Goncharov
b03af384af [JS IR] Add test with exception diagnostic of boolean in externals 2021-06-29 10:12:56 +00:00
Ilya Goncharov
82f979b11f [JS IR] Add property name to boolean in externals diagnostic 2021-06-29 10:12:55 +00:00
Ilya Goncharov
21a3494bca [JS IR] Add test with boolean in external interface
[JS IR] Add possibility to safely access Boolean in external declaration

[JS IR] Add diagnostic for booleans in externals
2021-06-29 10:12:54 +00:00
Tianyu Geng
2e049c1208 FIR DFA: fix CFG with normal arg after lambda [KT-46825]
The fix is a bit hacky, but it's very simple. In addition, it still does
not handle the case where the receiver is a lambda function. But such
case seems to be fairly rare in practice.
2021-06-29 10:46:41 +03:00
Tianyu Geng
b78b50e1f8 FIR DFA: workaround KT-46826 2021-06-29 10:46:40 +03:00
Tianyu Geng
0ecc752813 FIR checker: report SMARTCAST_IMPOSSIBLE for local variables 2021-06-29 10:46:38 +03:00
Alexander Shabalin
092750e215 Fix race in Lazy for the new MM 2021-06-29 06:29:57 +00:00
Alexander Shabalin
455625bcee Use FreezableAtomicReference in unhandled exception hook 2021-06-29 06:29:57 +00:00
Dmitry Gridin
fe855d09d8 fix idea compilation 2021-06-29 10:46:47 +07:00
Dmitry Gridin
274bae1d05 KtArrayAccessReference: remove redundant functions 2021-06-29 10:04:27 +07:00
Alexander Udalov
4b7fa44e80 CLI: fix resolution of Java records as single file roots
#KT-46764 Fixed
2021-06-29 01:22:08 +02:00
Ivan Kochurkin
e295849733 [FIR] Refactor FirSupertypesChecker: split big function on small ones 2021-06-29 02:00:11 +03:00
Ivan Kochurkin
fb9ce06ff5 [FIR] Implement DELEGATION_NOT_TO_INTERFACE 2021-06-29 02:00:11 +03:00
Ivan Kochurkin
c3a6ba52f6 [FIR] Implement CLASS_CANNOT_BE_EXTENDED_DIRECTLY 2021-06-29 02:00:10 +03:00
Ivan Kochurkin
92d7a61b4f [FIR] Implement INCONSISTENT_TYPE_PARAMETER_VALUES, INCONSISTENT_TYPE_PARAMETER_BOUNDS 2021-06-29 02:00:09 +03:00
Ivan Kochurkin
ec20f52707 [FIR] Implement EXPANDED_TYPE_CANNOT_BE_INHERITED, PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE
Add `starAsModifier` to `modifierSetPosition`
2021-06-29 02:00:08 +03:00
Ivan Kochurkin
937846b62d [FIR] Implement TYPEALIAS_SHOULD_EXPAND_TO_CLASS 2021-06-29 02:00:06 +03:00
Ivan Kochurkin
e8a790993b [FIR] Add ConeUnsupportedDynamicType 2021-06-29 02:00:03 +03:00
Denis.Zharkov
0ec693db89 Fix parsing regression related to T!!
^KT-47445 Fixed
2021-06-28 21:48:13 +03:00
Dmitry Petrov
768afc5ba4 JVM_IR KT-47492 fix 'for' loop generation 2021-06-28 21:07:54 +03:00
Roman Artemev
6993b86d3b [IR] Fix IrCapturedType equals/hashCode
It could lead to SOE if CT has itself as superType
- fix KT-47424
2021-06-28 20:43:14 +03:00
Dmitry Petrov
7ccefebf1c PSI2IR flatten more levels of indirection to avoid SOE in big exprs 2021-06-28 18:18:27 +03:00
Igor Yakovlev
cd0ea7f7f7 [FIR] Add explicit types to needReplacePhase transformers methods 2021-06-28 17:21:43 +03:00
Igor Yakovlev
30c381f16d [FIR] Fix invalid CallableId for methods in anonymous objects 2021-06-28 17:21:42 +03:00
Abduqodiri Qurbonzoda
47aa04d55d Test fix: java6 doesn't throw on invalid AbstractMutableList.addAll index
If the collection of elements to be added is empty, java6 implementation
of AbstractMutableList.addAll doesn't throw on invalid index.

The failing test was introduced in 59031543e2
which fixed #KT-47211.
2021-06-28 13:58:41 +00:00
Zalim Bashorov
a908e5576d [JS] Extract sourcemap generating related files to a separate module
It's required to reuse the same infrastructure in the new backend.
2021-06-28 16:04:09 +03:00
sebastian.sellmair
a63c179227 KotlinNativePlatformDependencies: Ensure 'commonizeNativeDistributionTask' is registered when 'isAllowCommonizer' is true 2021-06-28 13:00:19 +00:00
Svyatoslav Scherbina
b3980f9555 kotlin-native/samples: fix cocoapods after faulty cherry-pick 64129314
Move its source file to where it belongs.
2021-06-28 12:56:09 +00:00
Dmitry Petrov
560c269e05 PSI2IR KT-47450 prevent SOE when generating IR for deep expressions 2021-06-28 15:41:41 +03:00
Dmitriy Novozhilov
c4d9945782 Fix JPS build after removal of IDE plugin from repo 2021-06-28 14:32:24 +03:00
Ilya Goncharov
b76cbdaa41 [Gradle, JS] Remove redundant worksapces properties in yarn extensions 2021-06-28 13:38:04 +03:00
Ilya Goncharov
e3c291db27 [Gradle, JS] Not rewrite package.json if json was not changed 2021-06-28 13:38:03 +03:00
Ilya Goncharov
6219eb24c0 [Gradle, JS] Remove redundant test 2021-06-28 13:38:02 +03:00
Ilya Goncharov
1cc5a9493c [Gradle, JS] RootPackageJson task with up-to-date status 2021-06-28 13:38:01 +03:00
Ilya Goncharov
f182a1c750 [Gradle, JS] Sort for tools npm dependencies 2021-06-28 13:37:58 +03:00
Ilya Goncharov
3fc2a77281 [Gradle, JS] Remove redundant caching infrastructure 2021-06-28 13:37:57 +03:00
Ilya Goncharov
4d2376ac4c [Gradle, JS] Use package.json files instead of pre-package.json 2021-06-28 13:37:55 +03:00
Ilya Goncharov
f8bd440356 [Gradle, JS] Not force to write package.json in rootPackageJson 2021-06-28 13:37:53 +03:00
Ilya Goncharov
c4a1053aa7 [Gradle, JS] Add imported packages as workspace, not file dependencies 2021-06-28 13:37:52 +03:00
Alexander Udalov
f430d569d0 Fix warnings in js-ir/runtime/jsIntrinsics.kt
Suppress "UNUSED_PARAMETER" to fix compilation warnings. Also suppress
"unused" to make the file less yellow in the IDE.

Also enable `-Werror`, unless Gradle property
`kotlin.build.disable.werror` is set to true.
2021-06-28 12:19:35 +02:00
Svyatoslav Scherbina
eeffa49cd9 Native: don't generate .companion in ObjCExport if the companion is not exported
^KT-47462 Fixed
2021-06-28 08:19:12 +00:00
Svyatoslav Scherbina
786cb47450 Native: improve ObjCExport test for companion enum entry clash 2021-06-28 08:19:11 +00:00
Ivan Gavrilovic
929c4624cc KT-47416: Pass Android annotationProcessorOptions to kapt
This commits makes sure that "static" DSL options from
`android.javaCompileOptions.annotationProcessorOptions`
are passed to KAPT when running w/o kotlinc.

A regression was introduced in 19708cfa87.

Fixes #KT-47416
Test: Kapt3AndroidIT.testStaticDslOptionsPassedToKapt
2021-06-28 09:10:53 +02:00
Anton Bannykh
d303b783be KLIB: serialization support for global signatures and lowered IR features
Including:
- returnable blocks
- raw function references
- standalone type and value parameters
- file symbols
2021-06-27 22:56:35 +03:00
Anton Bannykh
6f01789139 IR: public symbols for the new global signatures 2021-06-27 22:56:35 +03:00
Anton Bannykh
aa5e7c65be KLIB: queue modules instead of ModuleDeserializationState
This approach is more general and expandable.
2021-06-27 22:56:35 +03:00
Anton Bannykh
e4707b236b JS IC: new signatures
Lowered IR might have cross-file references for fields, type parameters
and other stuff. Thus there is a need to make file-local and scope-local
signatures unique at least within a module.
2021-06-27 22:56:34 +03:00
Anton Bannykh
eba0661016 JS IC: .proto update 2021-06-27 22:56:34 +03:00
Anton Bannykh
b77d481ac6 IR: hide assert behind a flag
In JS IC the symbol might be unbound at this moment
2021-06-27 22:56:34 +03:00
Anton Bannykh
dbeb09af89 IR: fix SecondaryCtorLowering.kt 2021-06-27 22:56:34 +03:00
Anton Bannykh
bd4e7ffef8 JS PIR: store signatures for lowered declarations inside PIR declarations 2021-06-27 22:56:33 +03:00
Anton Bannykh
e0bdabcf61 JS IR: fix js SAM lowering 2021-06-27 22:56:33 +03:00
Anton Bannykh
9462131014 JS IR: fix offsets in BlockDecompositionLowering 2021-06-27 22:56:33 +03:00
Anton Bannykh
600099585d IR: refactor IdSignatureSerializer
Use a separate instance for each file.
2021-06-27 22:56:33 +03:00
Yahor Berdnikau
87dd357ec6 Add Gradle test task to run Gradle and Kotlin daemon tests.
These tests could not run in parallel, as they could not share
Gradle or Kotlin daemons with other running in parallel tests.

^KT-45745 In Progress
2021-06-27 21:35:54 +02:00
Andrey Zinovyev
c8fa8b0444 [lombok] Don't fail on fake overrides
#KT-47455 Fixes
2021-06-27 13:46:09 +03:00
Dmitriy Novozhilov
80b81934de Advance bootstrap to 1.5.30-dev-2862 2021-06-26 18:18:43 +03:00
Dmitriy Novozhilov
a8501bcef5 [FE 1.0] Fix message of INTEGER_OPERATOR_RESOLVE_WILL_CHANGE warning
^KT-47446 Fixed
2021-06-26 13:46:27 +03:00
Mikhael Bogdanov
5f62b72c82 Properly process big types 2021-06-26 06:10:16 +02:00
Mikhael Bogdanov
0fd1f549a9 Properly process special symbols during indy-with-constants concatenation
#KT-47320 Fixed
2021-06-26 06:10:16 +02:00
Zalim Bashorov
e947556aaa [IR] Use separate directories for each module for IR dumps
It allows avoiding overwriting content generated for other modules.

Also, added using additional ".kt" prefix to file extension for dumps generated with  Kotlin like syntax.
2021-06-26 01:38:04 +03:00
Alexander Shabalin
28b6427d3e Make FreezableAtomicReference atomic when unfrozen for the new MM. 2021-06-25 21:18:37 +00:00
Alexander Likhachev
518e8691b7 [Gradle, JS] Remove duplicate minimal Gradle version requirement
Minimal Gradle version for all Kotlin plugins is now 6.1 and minimal Gradle versions for all integration tests is set to 6.1.1
2021-06-25 22:40:06 +03:00
Alexander Likhachev
e8e95e6476 [Gradle, JS] Add test for KT-47154 regression
#KT-47154 Fixed
2021-06-25 22:40:04 +03:00
Alexander Likhachev
26510190cc [Gradle, JS] Include compiler type into library filter cache key
Previous fix could lead to unresolved symbols from main implementation in test compilation when module is compiled with both JS (IR and legacy) compilers because of single cached filter for both compileTestKotlinJsLegacy and compileTestKotlinJsIr tasks
#KT-47154 In Progress
2021-06-25 22:40:03 +03:00
Ivan Kochurkin
568eb255f5 [FIR] Split UpperBoundViolated checkers on two files (expression and declaration), add FirUpperBoundViolatedHelpers 2021-06-25 20:57:48 +03:00
Ivan Kochurkin
a26ffde820 [FIR] Correct support of projections and type aliases for UPPER_BOUND_VIOLATED, extend tests 2021-06-25 20:57:47 +03:00
Ivan Kochurkin
66e2b44272 [FIR] Implement UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION diagnostics, fix handling of UPPER_BOUND_VIOLATED 2021-06-25 20:57:46 +03:00
Ivan Kochurkin
5741374883 [FIR] Report UPPER_BOUND_VIOLATED only on checkers stage, fix detection of missing cases and testData 2021-06-25 20:57:45 +03:00
Ivan Kochurkin
ada14413e0 [FIR] Fix location of UPPER_BOUND_VIOLATED, fix detecting of several diagnostics, simplify FirUpperBoundViolatedChecker.kt 2021-06-25 20:57:44 +03:00
Dmitry Petrov
1298ba431b JVM_IR KT-47449 handle star projection arguments in default lambda types 2021-06-25 20:42:22 +03:00
Yahor Berdnikau
5486fec0f9 Validate Java and Kotlin target compatibility have same value.
This will ensure compiled java sources and kotlin sources class files
has the same bytecode version.

^KT-45611 Fixed
^KT-43095 Fixed
2021-06-25 16:28:57 +00:00
Yahor Berdnikau
6d929a8c3b Ensure toolchain is properly configured.
User specified toolchain maybe configured after initial task
configuration action will happen.

^KT-43095 In Progress
2021-06-25 16:28:56 +00:00
Yahor Berdnikau
4e556af54d Rename KotlinJavaToolchainProvider to DefaultKotlinJavaToolchain.
'Provider' suffix doesn't make sense.

^KT-45611 In Progress
^KT-43095 In Progress
2021-06-25 16:28:56 +00:00
Yahor Berdnikau
af2f716f4d Set 'jvmTarget' value on toolchain configuration.
Toolchain will set 'kotlinOptions.jvmTarget' value to the toolchain
jdk version, if 'jvmTarget' is not explicitly set by user.

If toolchain is not configured, 'jvmTarget' field uses default value,
which is now - "1.8".

^KT-45611 In Progress
^KT-43095 In Progress
2021-06-25 16:28:55 +00:00
Yahor Berdnikau
430306b23d Change 'jvmTarget' backing property visibility to internal.
Allows to check if this property was updated by the user or not.

^KT-45611 In Progress
^KT-43095 In Progress
2021-06-25 16:28:54 +00:00
Denis.Zharkov
48d170a858 Regenerate DiagnosisCompilerTestFE10TestdataTestGenerated 2021-06-25 18:41:15 +03:00
Denis.Zharkov
7645663d12 Deprecate (V)::a reference resolution to companion in FE 1.0
^KT-45315 Fixed
2021-06-25 18:41:14 +03:00
Denis.Zharkov
46b297477c Deprecate ambiguous cases in FE 1.0: companion property vs enum entry
^KT-37591 Fixed
2021-06-25 18:41:12 +03:00
Dmitriy Novozhilov
24bb9a4e14 Approximate expected type before reporting INTEGER_OPERATOR_RESOLVE_WILL_CHANGE
^KT-47447 Fixed
2021-06-25 18:39:01 +03:00
Ilya Goncharov
5bfdd5be5f [Gradle, JS] SubPlugin environment to js ir link task 2021-06-25 14:15:58 +00:00
Dmitriy Novozhilov
05883afc0a Deprecate simplification of complex boolean constant expressions in whens and loops
^KT-39883 In Progress
2021-06-25 16:37:35 +03:00
Dmitriy Novozhilov
8a2e0cedf9 Add test for exhaustive when with subject of Boolean! type 2021-06-25 16:37:34 +03:00
Dmitriy Novozhilov
09994ee8ea [FIR] Make type of safe call always nullable
^KT-46860 In Progress
2021-06-25 16:37:32 +03:00
Dmitriy Novozhilov
f18e38a49f [FIR] Properly setup source element for FirSafeCallExpression 2021-06-25 16:37:31 +03:00
Dmitriy Novozhilov
26b9948e5f [FE 1.0] Make type of safe call always nullable
^KT-46860 In Progress
2021-06-25 16:37:30 +03:00
Dmitriy Novozhilov
805fad980f [FIR] Fix creating DEBUG_CALL_INFO for safe calls 2021-06-25 16:37:29 +03:00
Dmitriy Novozhilov
9116c341ba [FIR] Fix detecting selector for safe calls in light tree 2021-06-25 16:37:27 +03:00
Dmitry Savvinov
4f8c854ead Exclude stdlib-common from jvm-specific compilations and source sets
^KT-46936 Fixed

Note that it is the slightly hack-ish fix; the proper one would remove
the dependency from kotlin-stdlib to kotlin-stdlib-common
2021-06-25 15:17:07 +03:00
Dmitry Savvinov
fa869c2c2a Add test on KT-46936 2021-06-25 15:17:06 +03:00
Dmitriy Novozhilov
1bce49023d Advance bootstrap to 1.5.30-dev-2757 2021-06-25 13:25:48 +03:00
sebastian.sellmair
b2dda0769c [Commonizer] HierarchicalClassAndTypeAliasCommonizationTest: Ignore tests for ^KT-47434 2021-06-25 09:25:11 +00:00
sebastian.sellmair
c234999c09 [Commonizer] HierarchicalClassAndTypeAliasCommonizationTest: Ignore tests for ^KT-47433 2021-06-25 09:25:10 +00:00
sebastian.sellmair
815d71a923 [Commonizer] HierarchicalClassAndTypeAliasCommonizationTest: Ignore tests for ^KT-47432 2021-06-25 09:25:10 +00:00
sebastian.sellmair
eaa0eb2851 [Commonizer] HierarchicalClassAndTypeAliasCommonizationTest: Add function parameter tests 2021-06-25 09:25:09 +00:00
sebastian.sellmair
4bcae0cc6f [Commonizer] Add CommonizeNativeDistributionTest.commonize - unix platforms() 2021-06-25 09:25:08 +00:00
sebastian.sellmair
1adf8091b1 [Commonizer] HierarchicalClassAndTypeAliasCommonizationTest: Add tests for issues found during okio investigation 2021-06-25 09:25:07 +00:00
Abduqodiri Qurbonzoda
aabc00f53f Throw IllegalStateException from MapBuilder iterator.remove() #KT-47419 2021-06-24 22:59:15 +00:00
Anton Bannykh
1006eb0945 IR: fix offsets in constant folding lowering 2021-06-25 00:59:28 +03:00
Anton Bannykh
9d1a8b2d58 IR: fill type parameters in inline class static method delegation call 2021-06-25 00:59:27 +03:00
Anton Bannykh
61a08be6b4 JS IR: don't rename the local declarations
IR2JS handles clashing declarations anyway.
2021-06-25 00:59:25 +03:00
Anton Bannykh
a56cc89010 JS IR: fill enum constructor call type parameters 2021-06-25 00:59:24 +03:00
Anton Bannykh
eb0c13793b JS IR: introduce 'lower per module' mode
This mode is closer to how IC supposed to work - reusing work
from dependencies, not re-lowering them.
2021-06-25 00:59:23 +03:00
Anton Bannykh
a4cb70af31 JS IR: gather statement origins in one place
Preparing to serialize lowered IR
2021-06-25 00:59:22 +03:00
Anton Bannykh
1b2f4ad071 dumpKotlinLike: add a flag to treat else as true
Deserialized IR always has `true` instead of `else` branch.
Dumping `else` as `true` helps comparing regular and serialized IR.
2021-06-25 00:59:20 +03:00
Sergey Igushkin
cf2c686630 Fix kotlin-test variants for correct resolution in *DependenciesMetadata
Make Gradle choose the `commonVariant` when a capability-less dependency
on kotlin-test is resolved for configurations requesting the common
artifacts.

Issue #KTIJ-6098 Fixed
2021-06-24 19:49:14 +00:00
Tianyu Geng
84f8d4d315 FIR IDE: handle reference to package and outer classes
For a qualified name like `foo.bar.Outer.Inner`, FIR represents it as
one atomic FIR element. Hence, to properly resolve these names to the
corresponding package and class, we need some additional work.
2021-06-24 18:27:51 +02:00
Tianyu Geng
a537074e1e FIR: add a boolean tracking if a class ref resolves to the companion object 2021-06-24 18:27:50 +02:00
Tianyu Geng
45ccec3b64 FIR IDE: Add HLAddWhenRemainingBranchesIntention 2021-06-24 18:26:20 +02:00
Tianyu Geng
63c65edda2 FIR IDE: AddWhenRemainingBranchFix
The fix reuses logic that is already available from
FirWhenExhaustivenessTransformer to collect missing when branches. The
current logic unfortunately uses hackyAllowRunningOnEdt to shorten the
generated code.
2021-06-24 18:26:18 +02:00
Tianyu Geng
6ec247b861 FIR: accept when(nothing) {} as exhaustive
FE1.0 accepts this but FIR current rejects it.
2021-06-24 18:26:17 +02:00
pyos
26e3237b8c JVM_IR: never rename public/protected fields
And if that causes a platform declaration clash, that's not a problem
that can be solved without breaking the ABI anyway.

 #KT-47412 Fixed
2021-06-24 17:41:06 +03:00
Jinseong Jeon
ee02303816 FIR IDE/UAST: resolve call from KtUnaryExpression 2021-06-24 16:38:24 +02:00
Jinseong Jeon
ed2cf9afd7 FIR IDE: handle other FIR calls for KtBinaryExpression 2021-06-24 16:38:24 +02:00
Elena Lepilkina
85ecbcb8f0 [K/N] Changed inlineThreshold after BCE for varargs 2021-06-24 12:57:57 +00:00
Yahor Berdnikau
e57ac5f67b Fix flaky test.
Narrow down unexpected string, so it will not clash with other output.
In this case 'AutoCloseable' was printed when Gradle 7 was generating
api jar.
2021-06-24 14:08:24 +02:00
pyos
88320cbb05 JVM_IR: produce collection stubs in a stable order
This means not storing intermediate results in any HashSets.

 #KT-47411 Fixed
2021-06-24 14:47:49 +03:00
Pavel Punegov
6ae6209031 Native: exclude tests that fail due to the KT-47405 and KT-47408 2021-06-24 10:54:45 +00:00
Denis.Zharkov
c8c558b575 FIR: Use Any? expect type to the argument list of ==
^KT-47409 Related
2021-06-24 12:17:46 +03:00
Denis.Zharkov
4892ad42b9 FIR: Do not mark not found classes' based types from Java as error
The same happens in FE1.0
2021-06-24 12:17:45 +03:00
Denis.Zharkov
201dded237 FIR: Fix serialization of delegated members
^KT-47413 Relates
2021-06-24 12:17:43 +03:00
Alexander Shabalin
cc71069a3a Do not require freezing for Worker.executeAfter on experimental MM 2021-06-24 07:57:23 +00:00
Ilya Kirillov
16e9c74523 FIR IDE: fix testdata after introducing isStatic property for symbols 2021-06-23 22:22:19 +03:00
Tianyu Geng
476d1da1cf Rename SelfTargetingIntention#allowCaretInsideElement
The current method makes it a bit hard to understand its purpose.
2021-06-23 22:22:18 +03:00
Tianyu Geng
abcc716ffc Document org.jetbrains.kotlin.idea.intentions.SelfTargetingIntention#allowCaretInsideElement
Also update its usage so that the contract of this method is easier to
understand.
2021-06-23 22:22:17 +03:00
Tianyu Geng
5a1223e812 FIR IDE: don't add return for when expressions when converting to block
There doesn't seem to be a good reason why FE1.0 does this. Hence we
won't do it in FIR.
2021-06-23 22:22:15 +03:00
Tianyu Geng
55e7cc7ea3 FIR IDE: add HLConvertToBlockBodyIntention 2021-06-23 22:22:14 +03:00
Tianyu Geng
030749eaeb FIR IDE: make KtExpressionTypeProvider work for more cases
Currently it doesn't work for the following

* labeled expression
* annotated expressions
* object literal expressions
2021-06-23 22:22:13 +03:00
Tianyu Geng
3aa6cb25ba FIR IDE: Add ImportMemberIntention 2021-06-23 22:22:12 +03:00
Tianyu Geng
66d44f2471 FIR IDE: Add ImportAllMembersIntention 2021-06-23 22:22:10 +03:00
Tianyu Geng
8d69f32d04 FIR IDE: fix test infra swallowing test failure output 2021-06-23 22:22:09 +03:00
Tianyu Geng
22fbd2044c FIR IDE: make ref shortener strictly follow range restriction 2021-06-23 22:22:08 +03:00
Tianyu Geng
726d141589 FIR IDE: Add fine-grained control to KtReferenceShortener
This change makes it possible to control how references to a symbol should be shortened.
2021-06-23 22:22:07 +03:00
Ilya Kirillov
8ac2a48eaf Allow specify path of compiler extension points for ide tests 2021-06-23 20:36:20 +03:00
Dmitry Petrov
0104b1275f JVM_IR KT-47398 handle @EnhancedNullability String subject as in 1.0 2021-06-23 20:11:24 +03:00
Dmitry Petrov
c26d71c4ef JVM KT-47365 add box test 2021-06-23 20:11:23 +03:00
sebastian.sellmair
7535f142c0 [Commonizer] SetExtensions: isSubsetOf: Use == over identity check
^KT-47301
2021-06-23 13:43:46 +00:00
sebastian.sellmair
ae57641456 [Commonizer] deserializeCirTree.kt: Optimize imports
^KT-47301
2021-06-23 13:43:45 +00:00
sebastian.sellmair
6044c58333 [Gradle] NativeDistributionCommonizerTask: Cleanup up-to-date checker comments
^KT-47301
2021-06-23 13:43:44 +00:00
sebastian.sellmair
a643ce89ff [Commonizer] Add CommonizerQueueTest.test diamond output targets()
^KT-47301
2021-06-23 13:43:44 +00:00
sebastian.sellmair
770efb7ecb [Commonizer] Replace InputTargetsSelectorInterface with a simple function
^KT-47301
2021-06-23 13:43:43 +00:00
sebastian.sellmair
5a8b39e08d [Gradle] GetCommonizerTargetOfSourceSet: Simplify implementation by only relying on compilations 2021-06-23 13:43:42 +00:00
sebastian.sellmair
19b99d5d91 [Gradle] Project.getCommonizerTarget(sourceSet: KotlinSourceSet): Ignore orphan source sets
Orphan source set's (source sets without compilation) can't break any
compilation. The decision to ignore those source sets for determining
the platform was already done for the IDE import.
In order to stay consistent, this function also ignores orphans.
2021-06-23 13:43:41 +00:00
sebastian.sellmair
97ea9c2c16 [Gradle] Rename HierarchicalNativeDistributionCommonizerTask to NativeDistributionCommonizerTask
^KT-47301
2021-06-23 13:43:40 +00:00
sebastian.sellmair
91259569d7 [Gradle] Remove old NativeDistributionCommonizerTask.kt
- Remove kotlin.mpp.enableHierarchicalCommonization gradle property:
This had to be done, since newer optimizations are not compatible
with non-hierarchical commonization

^KT-47301
2021-06-23 13:43:39 +00:00
sebastian.sellmair
73ffc0d180 [Gradle] NativeDistributionCommonizationCache: Support associative commonization
^KT-47301
2021-06-23 13:43:38 +00:00
sebastian.sellmair
21cef41ba5 [Commonizer] AbstractCommonizationFromSourcesTest remove assertions on commonized leaf/platform libraries
Those assertions are not necessary anymore, since the commonizer is not
expected to produce any new "actuals" per given expect.
The IDE is supposed to analyze leaf source sets against the original
platform libraries.
2021-06-23 13:43:37 +00:00
sebastian.sellmair
42f60d981f [Commonizer] Implement associative commonization
^KT-47301 Verification Pending
2021-06-23 13:43:36 +00:00
Kirill Shmakov
5fdbcb3dd1 [K/N][debug] Update LLDB bundle to support Apple Silicon
This is related to KTIJ-18889
2021-06-23 15:13:05 +03:00
Nikita Bobko
5a6f07402b Fix 'Generate FIR Checker Components and FIR/IDE Diagnostics' run configuration 2021-06-23 14:06:08 +02:00
Ilmir Usmanov
435b522cc5 Minor. Unmute test 2021-06-23 11:18:25 +02:00
pyos
537ce05bc9 JVM_IR: assume function reference adapters are tail-call
Meaning, they never need continuation objects. This shouldn't affect
correctness (if the assumption is valid, the continuation object
should always have been removed in the end), but the phantom
continuation sometimes left behind unused accessors (and in case of
inline function references, those accessors would refer to non-existent
functions) - see the modified test and Kotlin/kotlinx.coroutines#2769.
2021-06-23 11:18:25 +02:00
Vasily Levchenko
635a0fb01c [build][performance]kotlin:kotlin-build-gradle-plugin 0.0.29 -> 0.0.30 2021-06-23 09:07:29 +00:00
Andrey Uskov
92b08dfcfb Revert "Unify the way to set compiler options using System.properties"
This reverts commit 28e4e775
2021-06-23 11:34:04 +03:00
Dmitry Petrov
f30fc4863c JVM add ABI tests for non-approximated SAM types
Note that resulting SAM method
    public final method accept(p0: java.lang.Object): void
has a signature less specific than the resulting bridge method
    public synthetic bridge method accept(p0: X): void
2021-06-22 21:13:57 +03:00
Dmitry Petrov
c77884f067 Refactor SAM type handling, replace non-approximated arguments with * 2021-06-22 21:13:56 +03:00
Victor Petukhov
4aeabb6b0f Use upper bound aware type approximator for intersection types inside sam types in contravariant positions to build proper types in terms of subtyping 2021-06-22 21:13:55 +03:00
Victor Petukhov
6a78e0a10c Introduce type parameter's upper bound aware type approximator for intersection types 2021-06-22 21:13:54 +03:00
Victor Petukhov
750f327878 Use receivers from candidate as a fallback during completion of callable references
^KT-45083 Fixed
2021-06-22 21:13:53 +03:00
Nikita Bobko
fe8f7cfcae settings.gradle: update list of FIR IDE modules & attach them only when latest platform is used 2021-06-22 18:43:51 +02:00
Andrey Uskov
28e4e77542 Unify the way to set compiler options using System.properties
Now compiler flags with boolean values which are controlled by system
properties could be set in similar way. The following syntax is
appropriate. For setting flag:
'-DflagName,'-DflagName=[y|Y|true|TRUE|yes|YES|on|ON]'
for unsetting flag:
'-DflagName=[n|N|false|FALSE|no|NO|off|OFF]'
2021-06-22 19:35:28 +03:00
Svyatoslav Scherbina
04e8140162 Native: emit _Nullable_result attribute when generating Objective-C header
^KT-47042 Fixed
2021-06-22 16:12:37 +00:00
Nikita Bobko
9bf802a188 Move some idea-frontend-fir testData from compiler to IDE repo
This testData isn't used here but used in IDE repo
2021-06-22 18:41:42 +03:00
Nikita Bobko
c35e0438b6 Switch disableKotlinPluginModules flag 2021-06-22 17:21:04 +03:00
sebastian.sellmair
2006f89260 KotlinTargetContainerWithNativeShortcuts: Remove macos arm based targets
^KT-47126 Verification Pending
2021-06-22 12:21:05 +00:00
Svyatoslav Scherbina
9b49d0cf76 Native: fix testObjCExport testdata after 53baef88
(was broken during rebase)
2021-06-22 12:49:09 +03:00
Svyatoslav Scherbina
53baef8892 Add more tests for Native ObjCExport virtual adapters machinery 2021-06-22 09:29:30 +00:00
Svyatoslav Scherbina
5d5628f56e Native: apply ObjCExport virtual adapters from interfaces of supers
Previously they were skipped, and this was an incorrect optimization:
even if super class implements the interface too, this doesn't mean
that virtual adapters provided by that interface are inherited
by non-exported subclass that needs them;
for example, this doesn't happen when the super class is exported
(i.e. Obj-C class is not created at runtime).

Remove incorrect optimization instead of making it more sophisticated,
because it is useless anyway.

^KT-46431 Fixed
2021-06-22 09:29:29 +00:00
Alexander Shabalin
b7fbe09ef4 Fix Experimental MM tests on mingw 2021-06-22 08:58:00 +00:00
Abduqodiri Qurbonzoda
6db5fc0a23 Use teamcity kotlinLibsRepo and kotlinNativeDistDir parameters 2021-06-22 08:40:58 +00:00
Abduqodiri Qurbonzoda
013a7fe62d Rename the project from kotlin-dokka-stdlib to kotlin-stdlib-docs 2021-06-22 08:40:57 +00:00
Abduqodiri Qurbonzoda
d8d9a2689d Add sourcelink to generated documentation 2021-06-22 08:40:57 +00:00
Abduqodiri Qurbonzoda
6a9b9dc0a5 Print extracting info 2021-06-22 08:40:56 +00:00
Abduqodiri Qurbonzoda
40e23d8366 Use local libs from kotlin/build/repo and kotlin/kotlin-native/dist 2021-06-22 08:40:55 +00:00
Abduqodiri Qurbonzoda
5611fdcf25 Handle TeamCity build environment 2021-06-22 08:40:55 +00:00
Abduqodiri Qurbonzoda
e5b4fa83cb Use local sources dirs 2021-06-22 08:40:54 +00:00
Abduqodiri Qurbonzoda
72b1459353 Remove dependency on dokka build configuration artifacts 2021-06-22 08:40:53 +00:00
Abduqodiri Qurbonzoda
b5be7ddc4c Remove redundant kotlin_sources configuration 2021-06-22 08:40:52 +00:00
Abduqodiri Qurbonzoda
9777888ed4 Remove redundant use of mac and windows binaries 2021-06-22 08:40:52 +00:00
Abduqodiri Qurbonzoda
feaef467cd Remove redundant configuration declarations 2021-06-22 08:40:51 +00:00
Abduqodiri Qurbonzoda
d5d5891476 Move kotlin-dokka-stdlib scripts to libraries/tools/ 2021-06-22 08:40:50 +00:00
Nikolay Krasko
b406689035 Re-enable ":compiler:android-tests" module 2021-06-22 11:02:51 +03:00
Nikolay Krasko
d6aedc3229 Ignore more tasks if disableKotlinPluginModules explicitly set 2021-06-22 11:02:49 +03:00
Konstantin Tskhovrebov
28b8237836 Adapt XCFramework for using with groovy dsl. 2021-06-22 07:13:06 +00:00
Konstantin Tskhovrebov
c906d62c55 Add debug symbols for XCFrameworks. 2021-06-22 07:13:05 +00:00
Konstantin Tskhovrebov
297d661107 Add Apple M1 platforms to fat plist mapper. 2021-06-22 07:13:04 +00:00
Konstantin Tskhovrebov
84ae3df8b6 Add 'XCFramework' extension for creating XCFrameworks.
#KT-42667
2021-06-22 07:13:03 +00:00
Viacheslav Kormushkin
9fa55a6809 Fixed cocoapods error: expected ';' after module name
#KT-44235
2021-06-22 05:10:52 +00:00
nataliya.valtman
f6b428f271 KT-34862 use abi snapshot instead of build history files
Use jar snapshot instead build history file to avoid using time stamps and support remote gradle cache
2021-06-22 07:48:14 +03:00
Nikita Bobko
e5fbd0e2d8 Publish :idea-frontend-api, :idea-frontend-fir, :idea-fir-low-level-api modules artifacts
These artifacts are used in Kotlin plugin
2021-06-22 03:06:18 +03:00
Nikita Bobko
8b018f0a40 frontend-api-generator: remove unused module dependencies 2021-06-22 03:06:17 +03:00
Nikita Bobko
938cd955e1 Remove :idea prefix in IDE FIR modules which are going to stay in kotlin repo
This commit fixes not possibility to build project with `disableKotlinPluginModules`
flag on because Gradle tries to resolve `:idea` module which is disabled
2021-06-22 03:06:16 +03:00
Georgy Bronnikov
40872dd4ca JVM_IR: fix parallel compilation
Non-static inline functions that return inline
classes need to be tracked when copying files for by-file lowering.

FIXED: KT-45680
2021-06-22 02:22:36 +03:00
Ilya Goncharov
594cc29dd2 [Gradle, JS] Necessary to use approach with traversing all source sets
Because common source sets included into JS compilation, it can be detected as JS associated compilations.
So necessary to set attribute about JS compiler attribute only (at least at the beginning) to JS only source sets (source sets which are not included into any non js compilations)

[Gradle, JS] Add test with resolving JS variant of MPP library

[Gradle, JS] Add additional filtering of JS targets

[Gradle, JS] Add test on local resolve

^KT-47163 fixed
^KT-47114 fixed
2021-06-21 21:22:35 +03:00
Jinseong Jeon
03f85bea8f FIR checker: report VAL_REASSIGNMENT on value parameter 2021-06-21 20:58:01 +03:00
Jinseong Jeon
2486555208 FIR checker: refactor VAL_REASSIGNMENT checker 2021-06-21 20:58:00 +03:00
Jinseong Jeon
338503a4ae FIR checker: minor cleanup in FirPropertyInitializationAnalyzer 2021-06-21 20:57:58 +03:00
Ilya Kirillov
06918769e7 FIR IDE: actualize testdata 2021-06-21 20:43:45 +03:00
Ilya Kirillov
80c6506a21 FIR IDE: return back symbol restoring to symbol testss 2021-06-21 20:43:44 +03:00
Ilya Kirillov
dbba9297ff FIR IDE: restore InnerDeclarationsResolvePhaseTest 2021-06-21 20:43:43 +03:00
Ilya Kirillov
a9715de704 FIR IDE: fix leaking of FirJavaElementFinder in tests 2021-06-21 20:43:42 +03:00
Ilya Kirillov
61651c685c FIR IDE: restore FirLazyDeclarationResolveTest 2021-06-21 20:43:40 +03:00
Ilya Kirillov
c70629c22a FIR IDE: migrate LL API test to the test infrastructure from HL API 2021-06-21 20:43:39 +03:00
Dmitry Petrov
c19792e7c5 JVM_IR KT-47326 downcast field receiver on JvmField lowering 2021-06-21 19:17:54 +03:00
Alexander Shabalin
ebc4e10684 Fix GC stress test. 2021-06-21 16:07:57 +00:00
pyos
cf660cf24a JVM_IR: expect unboxed return value from suspend default stubs
#KT-47206 Fixed
2021-06-21 18:53:31 +03:00
Mark Punzalan
578fcf2ebf FIR: Render fun status flag in FirRenderer. 2021-06-21 18:45:38 +03:00
Mark Punzalan
efe3f7b87e FIR: Do not load inline flag when deserializing properties; there is
no `inline` flag for serialized properties.

In order to test this, I added the changes to FirRenderer to make sure
the flag is not loaded. However, this revealed that the `inline` status
was propagated upward to the `FirProperty` during raw FIR building,
causing test failures.

I removed the upward propagation for `inline`. I also removed it for
`external` because it is incorrect: `external` on properties (used in
JS) should be separate from `external` on accessors (used in JNI
interop for JVM). The `external` flags are also serialized separately
for properties and accessors.
2021-06-21 18:45:37 +03:00
Yahor Berdnikau
030697d430 Restore removed 'kotlinPluginVersion' property.
And marked it as '@Deprecated'.

^KT-47317 Fixed
2021-06-21 17:38:57 +02:00
Marina Shishkina
b68c00e0e9 rrr/1.5.20-release/ayalyshev/change-notes
Update links in the plugin description

Update UTM for the kotlinlang link

Add change notes for 1.5.20

Co-authored-by: Anton Yalyshev <Anton.Yalyshev@jetbrains.com>
2021-06-21 18:30:05 +03:00
pyos
913ac289ed JVM_IR: extract boolean-valued DFS on IR elements into a helper 2021-06-21 16:19:24 +03:00
pyos
ee4d9a89ea JVM_IR: read inline fun bytecode to detect unused property references
I.e. optimize `$$delegatedProperties` in the same way as the old
backend. This is more reliable than trying to match bytecode.
2021-06-21 16:19:23 +03:00
pyos
bd6d96114b JVM_IR: generate shorter bytecode for reflected property references 2021-06-21 16:19:23 +03:00
Alexander Shabalin
7079ad49bc Add a test on attaching new threads while collecting 2021-06-21 12:26:01 +00:00
Elena Lepilkina
7c45154fc5 [K/N] Added copy array benchmark 2021-06-21 12:23:25 +00:00
Jinseong Jeon
bc09d94717 FIR UAST: running resolve API tests for both plugins 2021-06-21 13:49:47 +03:00
Jinseong Jeon
610b68c29d FIR/UAST: commonize expressions with label 2021-06-21 13:49:46 +03:00
Jinseong Jeon
fa613a32b2 FIR/UAST: commonize safe qualified expression 2021-06-21 13:49:45 +03:00
Jinseong Jeon
2999d0bd4b FIR/UAST: commonize double colon expressions 2021-06-21 13:49:44 +03:00
Jinseong Jeon
77e8aed995 FIR/UAST: move multi resolve utils/APIs to the base module/service 2021-06-21 13:49:42 +03:00
Jinseong Jeon
e870bf7399 FIR/UAST: commonize simple reference expression 2021-06-21 13:49:41 +03:00
Jinseong Jeon
4ec745abd7 FIR: relax simple type requirement in AbstractTypeMapper
The counterparts in old FE don't have such restriction, so it can
map a type that has a flexible type as a type argument to JVM type,
e.g., Stream<String..String?>
2021-06-21 13:49:40 +03:00
Jinseong Jeon
08e486d1a7 FIR/UAST: commonize dot qualified expression 2021-06-21 13:49:39 +03:00
Ilya Kirillov
8f70ef41f0 FIR IDE: consider resolve inside completion candidate checker 2021-06-21 13:43:49 +03:00
Ilya Kirillov
9d07832175 fix "FIR IDE: implement completion for variables with functional types with receivers" 2021-06-21 13:43:48 +03:00
Ilya Kirillov
0ebb9cc4a6 FIR IDE: extract completion groups to object 2021-06-21 13:43:47 +03:00
Ilya Kirillov
20f2e4f313 FIR IDE: introduce basic weighting for completion based by groups 2021-06-21 13:43:46 +03:00
Ilya Kirillov
a5edbd531b FIR IDE: add ::class/::class.java to callable references completion 2021-06-21 13:43:45 +03:00
Ilya Kirillov
915c8b7996 FIR IDE: implement completion for variables with functional types with receivers 2021-06-21 13:43:44 +03:00
Ilya Kirillov
167917cf07 FIR IDE: ignore attributes in completion tests 2021-06-21 13:43:43 +03:00
Ilya Kirillov
72e26771d8 FIR IDE: do not require resolve bodies toc check candidates for completion 2021-06-21 13:43:41 +03:00
Ilya Kirillov
b8248f0197 FIR IDE: do not ignore parameters for extension applicability for completion 2021-06-21 13:43:40 +03:00
Ilya Kirillov
ae9ac33f0f FIR IDE: implement completion for infix functions 2021-06-21 13:43:39 +03:00
Ilya Kirillov
2ffc7ad0a0 FIR IDE: implement completion for callable references 2021-06-21 13:43:38 +03:00
Dmitriy Novozhilov
a42e9c236a [FIR] Fix PSI types of some diagnostics 2021-06-21 13:13:18 +03:00
Dmitriy Novozhilov
b218573bb3 [FIR] Add pretty toString to FirDiagnosticFactory 2021-06-21 13:13:17 +03:00
Dmitriy Novozhilov
3564db4f7b [FIR] Add assertion which checks that diagnostic is reported on proper PSI element 2021-06-21 13:13:17 +03:00
Dmitriy Novozhilov
a288b8b00e [FIR] Remove useless type parameters from classes related to diagnostics
Generics removed from:
 - FirPsiSourceElement
 - FirDiagnostic
 - FirDiagnosticRenderer
 - FirDiagnosticFactory
2021-06-21 13:13:17 +03:00
Dmitriy Novozhilov
386f6d9331 [FIR] Safe KClass of PSI type in diagnostic factory 2021-06-21 13:13:17 +03:00
Dmitriy Novozhilov
399b7aceef [FIR] Fix reporting diagnostics in CLI which was broken in previous commit
Note: reporting properly works only for PSI
2021-06-21 13:13:17 +03:00
Dmitriy Novozhilov
d807ac2f05 [FIR] Don't inherit FIR diagnostics from FE 1.0 diagnostics 2021-06-21 13:13:17 +03:00
Dmitriy Novozhilov
3d544be655 [FIR] Add ability to specify custom position strategy for specific diagnostic 2021-06-21 13:13:17 +03:00
Dmitriy Novozhilov
9ef712c096 [FIR] Prohibit using FirDiagnosticFactory.on for creating diagnostics
In most cases it's better to use `FirDiagnosticReporter.reportOn`, so
  `on` methods now marked as opt in
2021-06-21 13:13:16 +03:00
Andrei Klunnyi
89801a1ac7 KT-44841 Move sealed: no warning on splitting hierarchy (JPS)
To provide similar behavior for both Gradle and JPS projects target and
source directories are now taken into account.

Prior to this commit AbstractMoveTest.kt contained a hack allowing not
to create empty target directories. It breaks updated logic of the move
check and therefore is removed.
To commit empty target directories under 'before' to git one needs to
put something in them (git ignores dirs otherwise). Hence .gitignore-s.

^KT-44841 Fixed
2021-06-21 09:51:17 +00:00
Svyatoslav Scherbina
b961812efd Native: fix thread state when calling ObjC completion for Kotlin suspend 2021-06-21 09:37:25 +00:00
Ilya Kirillov
87c6ab493b FIR IDE: mute some highlighting tests
They may fail if they run separately
2021-06-21 04:15:37 +02:00
Ilya Kirillov
bbefc064a9 FIR IDE: fix EntityWasGarbageCollectedException for KtType 2021-06-21 03:38:25 +02:00
Ilya Kirillov
f00170eb31 FIR IDE: add missing runtime dependencies for tests 2021-06-21 02:50:11 +02:00
Ilya Kirillov
caf4eba2df FIR IDE: do not run tests from idea-fir module in parallel 2021-06-21 02:19:23 +02:00
Ilya Kirillov
dd0a91cc15 FIR IDE: invalidate caches between lightclasses tests 2021-06-21 00:51:31 +02:00
Ilya Kirillov
c2ae434737 Remove // FIR_IDE_IGNORE directive from passing tests 2021-06-21 00:51:31 +02:00
Ilya Kirillov
822590a62b FIR IDE: temporary disable AbstractFirLazyDeclarationResolveTest.kt 2021-06-21 00:51:31 +02:00
Ilya Kirillov
90f6d458b5 FIR IDE: fix test task name 2021-06-21 00:51:31 +02:00
Ilya Kirillov
f20dd8b673 FIR IDE: fixes after rebase 2021-06-21 00:51:30 +02:00
Ilya Kirillov
cf04be5207 FIR IDE: temp mute failing light class test 2021-06-21 00:51:30 +02:00
Ilya Kirillov
e9d1fb7c40 FIR IDE: mute completion tests failing with "Class LinkedHashMap was not found" 2021-06-21 00:51:30 +02:00
Ilya Kirillov
3e42ae03a9 Move frontend api modules out of ide modules 2021-06-20 22:07:49 +02:00
Ilya Kirillov
495a5136bb extract frontendApiTests to separate gradle task 2021-06-20 22:07:49 +02:00
Ilya Kirillov
d5cd4955cc FIR IDE: temporary update testdata of lazy resovle test 2021-06-20 22:07:46 +02:00
Ilya Kirillov
72b8593240 FIR IDE: do not use IJ test infrastructure in frontend-api-fir tests 2021-06-20 22:07:31 +02:00
Ilya Kirillov
606c3c136c FIR IDE: remove dependency to IDEA from low-level-api fir impl module 2021-06-20 22:07:28 +02:00
Ilya Kirillov
0c5883cbe0 FIR IDE: do not depend on IDEA modules in frontend-api 2021-06-20 22:07:15 +02:00
Ilya Kirillov
28dbfeb845 Move KtReference interface to psi module 2021-06-20 22:07:15 +02:00
Ilya Kirillov
796baf261d FIR IDE: move KtIconProvider out of idea-frontend-api module 2021-06-20 22:07:15 +02:00
Ilya Kirillov
75331b3448 FIR IDE: abstract low-level-api from dependency on idea 2021-06-20 22:07:11 +02:00
Ilya Kirillov
a483098303 FIR IDE: abstract DeclarationProvider 2021-06-20 22:02:17 +02:00
Ilya Kirillov
7fe2adc37e FIR IDE: do not use helper methods unavailable in intellij-core 2021-06-20 22:02:17 +02:00
Ilya Kirillov
32919489f4 FIR IDE: separate index helper in LL API and completion 2021-06-20 22:02:17 +02:00
Jinseong Jeon
7a5d61928b FIR/IDE: migrate FIR evaluator to idea-frontend-fir 2021-06-19 21:58:48 -07:00
Jinseong Jeon
fcdb8866d2 FIR: rewrite evaluator to use eval utils in frontend.common 2021-06-19 21:58:47 -07:00
Jinseong Jeon
477c1c8cd7 Migrate CompileTimeType and OperationsMap to frontend.common 2021-06-19 21:58:47 -07:00
Jinseong Jeon
833761ac3c FIR IDE/UAST: add KtCompileTimeConstantProvider with evaluate API 2021-06-19 21:58:41 -07:00
Jinseong Jeon
7d157f006b Rename CompileTimeConstantEvaluator to have Fir prefix 2021-06-19 21:35:36 -07:00
Jinseong Jeon
720104de78 Temporarily allow deprecated conversions in FIR operations map
Also, switch to the new copyright header
2021-06-19 21:35:35 -07:00
Jinseong Jeon
fc5d1d8cb5 FirConstKind has been renamed to ConstantValueKind (d243319) 2021-06-19 21:35:35 -07:00
Jinseong Jeon
bb297b87bd Avoid hard-coded operator names in CompileTimeConstantEvaluator 2021-06-19 21:35:34 -07:00
Jinseong Jeon
a969924248 FIR: generate operations map for CompileTimeConstantEvaluator 2021-06-19 21:35:34 -07:00
Jinseong Jeon
5e2525175e Introduce fir.evaluate module with CompileTimeConstantEvaluator 2021-06-19 21:35:33 -07:00
Igor Yakovlev
ec80c21fd1 [FIR IDE] Fix lazy resolve for local declarations 2021-06-19 19:23:24 +02:00
Igor Yakovlev
c17a67ba61 [FIR IDE] Fix invalid collecting designation for local declarations 2021-06-19 19:23:24 +02:00
Igor Yakovlev
41c42a5016 [FIR IDE] Remove session scope default parameter from lazy resolve interface 2021-06-19 19:23:24 +02:00
Igor Yakovlev
52765c333d [FIR IDE] Add test for local function lazy resolve and add phase into test data 2021-06-19 19:23:24 +02:00
Igor Yakovlev
2319a53fae [FIR] Fixed invalid phase for values value parameter 2021-06-19 19:23:23 +02:00
Igor Yakovlev
8012429e31 [FIR IDE] Fix loop inheritance tests 2021-06-19 19:23:23 +02:00
Igor Yakovlev
3a1057eb60 [FIR IDE] Enable passing spec tests 2021-06-19 19:23:23 +02:00
Igor Yakovlev
b612e13061 [FIR IDE] Always resolve to Body in ide fir renderer 2021-06-19 19:23:23 +02:00
Igor Yakovlev
e900a1fa57 [FIR IDE] Fix local declarations resolve 2021-06-19 19:23:23 +02:00
Igor Yakovlev
4a212dc6a0 [FIR IDE] Fix unresolved supertype for typealiases 2021-06-19 19:23:23 +02:00
Igor Yakovlev
6c0bacc548 [FIR IDE] Fix invalid status for class symbols 2021-06-19 19:23:23 +02:00
Igor Yakovlev
21b1e4b072 [FIR IDE] Add lazy resolve phases tests 2021-06-19 19:23:23 +02:00
Igor Yakovlev
df1b41f05c [FIR IDE] Rename refactoring 2021-06-19 19:23:22 +02:00
Igor Yakovlev
eded837115 [FIR IDE] Add typed lazy resolve implementation 2021-06-19 19:23:22 +02:00
Igor Yakovlev
7a0391b9b3 [FIR IDE] Move refactoring for constructor of the FileStructure 2021-06-19 19:23:22 +02:00
Igor Yakovlev
a60be78898 [FIR IDE] Remove designation collecting for local declarations 2021-06-19 19:23:22 +02:00
Igor Yakovlev
0cbb29f494 [FIR IDE] Remove typed fir designation 2021-06-19 19:23:22 +02:00
Igor Yakovlev
a4dbf0ae57 [FIR IDE] Update class modifiers requirements for resolve phase 2021-06-19 19:23:22 +02:00
Igor Yakovlev
3573f5066b [FIR] Remove redundant println from RawFirBuilder 2021-06-19 19:23:22 +02:00
Igor Yakovlev
83382bea13 [FIR IDE] Concurrent identity cache for files 2021-06-19 19:23:21 +02:00
Igor Yakovlev
f98995f6cb [FIR IDE] Implement lazy designated resolve for all resolve FIR phases 2021-06-19 19:23:21 +02:00
Jinseong Jeon
cda1a7edbe FIR/UAST: commonize UAnnotationMethod 2021-06-19 11:39:46 +02:00
Jinseong Jeon
638b0beadb FIR UAST: unify UMethod creation 2021-06-19 11:39:46 +02:00
Jinseong Jeon
5ec5b7f041 FIR/UAST: commonize constructor declarations 2021-06-19 11:39:45 +02:00
Jinseong Jeon
cbaa645dbe FIR/UAST: commonize base UMethod 2021-06-19 11:39:45 +02:00
Jinseong Jeon
4a06ca637a FIR/UAST: commonize anonymous UClass 2021-06-19 11:39:45 +02:00
Jinseong Jeon
3bd4cb274d FIR/UAST: commonize invalid UClass 2021-06-19 11:39:44 +02:00
Jinseong Jeon
1749c90083 FIR/UAST: commonize base UClass (with bogus annotation abstraction) 2021-06-19 11:39:44 +02:00
Jinseong Jeon
06c20bb10e FIR/UAST: commonize abstraction of Kotlin UClass 2021-06-19 11:39:43 +02:00
Jinseong Jeon
0c011f4e73 UAST: place method declarations together 2021-06-19 11:39:43 +02:00
Jinseong Jeon
beddf03f74 FIR/UAST: convert annotation via base converter 2021-06-19 11:39:42 +02:00
Jinseong Jeon
33ff90a6da FIR/UAST: commonize named/vararg expressions 2021-06-19 11:39:42 +02:00
Jinseong Jeon
dcf99e9fd1 UAST: delete redundant file
This is rather a test input, and indeed there is testData/Suspend.kt
2021-06-19 11:39:42 +02:00
Jinseong Jeon
4e4b104488 FIR/UAST: commonize expression list 2021-06-19 11:39:41 +02:00
Jinseong Jeon
2e58b57db9 UAST: remove redundant override: expression list's evaluate()
The super function in `KotlinEvaluatableUElement` is almost same,
except for handling of `UnsignedErrorValueTypeConstant`.
Such handling was added later, so I assume the addition to this override
was missed. In any cases, this override is unnecessary.
2021-06-19 11:39:41 +02:00
Jinseong Jeon
31d1c002c5 FIR UAST: implement constructors/delegations
But, the logic is identical to the counterpart in FE1.0 UAST
Many declaration abstractions, such as (primary|secondary) constructor
methods and class, are very similar, and thus can be commonized soon
once the remaining parts (in particular, annotations) are done.
2021-06-19 11:39:40 +02:00
Nikita Bobko
8b3c6489da Fix kotlin resources iml path 2021-06-18 17:42:23 +02:00
Nikita Bobko
306f8b7358 [imltogradle] Add "imls in same directory are not allowed" check 2021-06-18 17:42:23 +02:00
Ilya Goncharov
eed23ddbe3 [JS, Frontend] Add test with extension member in external interface 2021-06-18 17:20:57 +03:00
Ilya Goncharov
83c1a119ee [JS, Frontend] Add option to allow extension lambdas in externals 2021-06-18 17:20:56 +03:00
Svyatoslav Scherbina
2a54f1c610 Improve exception messages for kotlin.native.concurrent.* operations 2021-06-18 13:51:21 +00:00
nataliya.valtman
6a32e7bd5a Add typealias testcase for incremental compilation 2021-06-18 16:50:17 +03:00
Anton Bannykh
48fe46303d JS IR: declare intrinsics for lowerings in stdlib
- simplifies lowered IR serialization
- removes some hacks in jsOperators.kt
- intrinsics can be directly invoked in stdlib
2021-06-18 15:26:52 +03:00
Ilya Matveev
94384ce2ca [K/N][Runtime] Add a lock method to thread registry 2021-06-18 12:20:04 +00:00
Ilya Matveev
cece652412 [K/N][Runtime] Separate thread registering and making it 'Runnable'
The new GC will require threads to suspend right after registering
if Stop-The-World is requested. This patch changes the initial
thread state to kNative and adds a separate state switch right
after thread registering. This switch suspends if it is necessary.
2021-06-18 12:20:03 +00:00
Alexander Shabalin
e240b8a8ee Add a separate aggressive GC mode 2021-06-18 12:03:02 +00:00
Igor Chevdar
1cfe1c41ef [K/N][IR] Fixed problem with klib compilation
Fixes https://youtrack.jetbrains.com/issue/KT-46896
2021-06-18 16:21:24 +05:00
Igor Chevdar
421ff68cd6 [K/N][codegen] Fix for https://youtrack.jetbrains.com/issue/KT-47183 2021-06-18 15:57:45 +05:00
Yahor Berdnikau
7aa882b921 Add test for multiplatform plugin.
^KT-43095 In Progress
2021-06-18 10:50:26 +00:00
Yahor Berdnikau
0f1da3c412 Make GradleCompileTaskProvider compatible with configuration cache.
Refactor it such way that it could be used via Provider and
don't raise configuration cache errors.

^KT-45611 In Progress
^KT-43095 In Progress
2021-06-18 10:50:26 +00:00
Yahor Berdnikau
84ec4106f7 Don't set toolchain if it is not configured.
Before even when user did not configure toolchain, default toolchain
was still created, but with recent changes it does not make sense.

^KT-43095 In Progress
2021-06-18 10:50:25 +00:00
Yahor Berdnikau
1c9b013732 Change dsl method to 'jvmToolchain'.
This better reflects that applying toolchain only affects jvm
backend compilations.

^KT-43095 In Progress
2021-06-18 10:50:24 +00:00
Yahor Berdnikau
1a6bb5cd08 Allow to pass any object for 'jdkVersion'.
This object should be accepted by 'JavaVersion.toVersion' method.

^KT-45611 In Progress
2021-06-18 10:50:23 +00:00
Yahor Berdnikau
46d5df4991 Consider toolchain only as input for 'jdkHome' compilation option.
This change will limit toolchain scope only to the JVM compilations,
as Kotlin compiler itself does not care about JDK version it is running
 on and should always produce same output for non-JVM backends.
For JVM backend there is one condition - 'jdkHome' should always point
 to the same JDK version.

Few additional changes:
- allow to set specific JDK location even on Gradle versions 6.7+
- Fix typo in deprecation message

^KT-45611 In Progress
^KT-43095 In Progress
2021-06-18 10:50:23 +00:00
Yahor Berdnikau
1bb64ffa22 Revert "Print path to java executable Kotlin daemon was started with."
This reverts commit 3e69bcba47.
2021-06-18 10:50:22 +00:00
Yahor Berdnikau
f9ec6bb66a Revert "Optionally make java executable path contribute to the daemon id."
This reverts commit ac86ad252f.
2021-06-18 10:50:21 +00:00
Pavel Kunyavskiy
d7a3310042 [K/N] KT-43780: support of more convenient objects using from objC/Swift 2021-06-18 08:02:22 +00:00
Pavel Kunyavskiy
0952a95949 [K/N] reuse common code for companionObject util 2021-06-18 08:02:21 +00:00
Viacheslav Kormushkin
0b6d2cd21a Custom name support for fat frameworks
#KT-30805
2021-06-18 06:28:01 +00:00
Dmitry Petrov
ce107d06d4 JVM_IR add test for KT-47300 2021-06-17 21:40:30 +03:00
Roman Golyshev
1cd75b1e82 kotlin-stdlib:jvm-minimal-for-test -> kotlin-stdlib-jvm-minimal-for-test
Changed after cherry-picking 8baf570ee7
to the master-for-ide branch
2021-06-17 20:19:49 +03:00
Roman Golyshev
6ea4b8997b Add kotlin-stdlib-minimal-for-test.jar artefact to the published dependencies
Some compiler tests rely on this jar instead of the regular `stdlib`
2021-06-17 20:19:48 +03:00
Vyacheslav Gerasimov
73d4110c92 Build: Rollback kotlin-stdlib-jvm-minimal-for-test publication
Continue publishing to the internal/repo only
2021-06-17 19:43:11 +03:00
Vyacheslav Gerasimov
58f1fb644f Build: Stop publishing jars with original classifier
#KTI-580
2021-06-17 19:43:10 +03:00
Vyacheslav Gerasimov
fb805028c1 Build: Add runtimeJar variant to the default java component if present 2021-06-17 19:43:09 +03:00
Vyacheslav Gerasimov
a0469a1d62 Build: Make Gradle plugin publications reuse POMs from the main one
#KTI-571
2021-06-17 19:43:07 +03:00
Nikolay Krasko
80677c88cb Update gradle task in generated files 2021-06-17 18:36:10 +03:00
Nikolay Krasko
c8ae9a7090 [imltogradle] Speedup files traversing by ignoring directories 2021-06-17 18:36:09 +03:00
Nikolay Krasko
7e8168a7e6 Ignore more boostrap libraries in dependency verification 2021-06-17 18:36:08 +03:00
Nikolay Krasko
d72f1097d7 Cleanup dependency verification for 211 kotlin-ide 2021-06-17 18:36:07 +03:00
Nikolay Krasko
6139f095e7 Disable dependencies verification for kotlin-ide projects 2021-06-17 18:36:06 +03:00
Nikolay Krasko
71ee9cf1be Fix generateIdeaGradleFiles on Windows 2021-06-17 18:36:04 +03:00
Ilya Kirillov
8c69913640 FIR IDE: temporary ignore failing intention tests 2021-06-17 17:27:00 +03:00
Mark Punzalan
97c10b0b84 FIR IDE: Change PSI element type for NO_COMPANION_OBJECT and
EXPRESSION_EXPECTED_PACKAGE_FOUND from KtSimpleNameExpression to
KtExpression (source can be KtDotQualifiedExpression).
2021-06-17 17:26:58 +03:00
Alexander Shabalin
91a852d3fd Fix integer conversion on 32-bit 2021-06-17 14:16:16 +00:00
Margarita Bobova
eaed67df29 Move 1.4.x changelog to a separate file 2021-06-17 14:50:36 +03:00
Ivan Kochurkin
a0aaf42fb1 Some string and minor optimizations 2021-06-17 13:49:08 +03:00
Ivan Kochurkin
bc3c05a3bd [FIR] Replace lists with Long in Modifier, refactor Modifier and derived classes 2021-06-17 13:49:08 +03:00
Ivan Kochurkin
6199b85eb9 [FIR] Introduce ModifierKind and optimize Modifier in lightTree 2021-06-17 13:49:08 +03:00
Ivan Kochurkin
ce4e60afd3 [FIR] Simplify FirCyclicTypeBoundsChecker and replace PersistentList with MutableList 2021-06-17 13:49:07 +03:00
Ivan Kochurkin
1e430b7b03 [FIR] Replace PersistentList with MutableList in Context, simplify DeclarationConverter 2021-06-17 13:49:07 +03:00
Ivan Kochurkin
366017d267 [FIR] Replace PersistentList with MutableList in BodyResolveContext, LocalClassesNavigation 2021-06-17 13:49:06 +03:00
Andrey Zinovyev
d360932ebc [FIR] Fill overriddenSymbols for fake overridden IrProperty 2021-06-17 13:24:12 +03:00
Sergey Bogolepov
4f98a0e083 [Native] Introduce optInCacheableTargets
Create an explicit list of targets that have unstable compiler caches
in konan.properties. It allows to control all lists of cacheable targets
in a single place.
2021-06-17 09:19:44 +00:00
Roman Golyshev
108dd37242 Add possibility to use baseDir in CoroutineHelpersSourceFilesProvider 2021-06-17 02:41:32 +03:00
Nikita Nazarov
adec873118 [EE_IR] Update ignore directive 2021-06-17 02:40:04 +03:00
Alexander Shabalin
e3eec33b24 Add aggressively allocating stress test for GC 2021-06-16 21:34:05 +00:00
Alexander Shabalin
7ae59856cb Add internal MemoryUsageInfo object
Currently it only provides peak RSS usage for iOS, Linux, macOS and Windows.
2021-06-16 21:34:04 +00:00
Nikita Bobko
670d66984f Reduce Gradle configuration phase time in case when 'attachedIntellijVersion' flag is specified
Traversing intellij repo is long
2021-06-16 21:58:36 +03:00
Nikita Bobko
526a664077 [imltogradle] Add a bit of logging 2021-06-16 21:58:36 +03:00
Nikita Bobko
c954fa4900 Make it possible to attach community version of kotlin-ide 2021-06-16 21:58:34 +03:00
Roman Artemev
8ac5d03f02 [Test] fix module name in klib text tests
It failed on windows machines due to illegal '<' in path
2021-06-16 21:16:58 +03:00
Roman Artemev
56604a9654 [K/N] Promote kotlin-build-gradle-plugin version 0.0.29 -> 0.0.30
Missed fix
2021-06-16 21:16:57 +03:00
Roman Artemev
2c34888a57 [TEST] Add comment in klib text tests runner 2021-06-16 21:16:56 +03:00
Roman Artemev
71af11052a [TEST] Mute tests irText klib tests 2021-06-16 21:16:55 +03:00
Roman Artemev
e82552975d [TEST] support test muting in klib text tests runner 2021-06-16 21:16:54 +03:00
Roman Artemev
5bc884ce2b [KLIB] Fix fakeoverride builder
Set proper visibility in case of cross-module internal overrides.
TODO: KT-47192
2021-06-16 21:16:53 +03:00
Roman Artemev
0cb23a6e65 [KLIB] Fix serialization of loops with control statements in condition 2021-06-16 21:16:52 +03:00
Roman Artemev
e5c6a5b80d [IR] Clean up Fake Override builder a bit 2021-06-16 21:16:51 +03:00
Roman Artemev
1831c0a14b [IR] Support disabling of rendering IrErrorType inner KotlinType 2021-06-16 21:16:50 +03:00
Roman Artemev
2eac442705 [IR] Support stable order in IR dump
That mode is need to test deserialization of klibs
2021-06-16 21:16:49 +03:00
Roman Artemev
bbcd511c44 [TEST] fix irText testData
- support DELEGATED_MEMBER overrides
2021-06-16 21:16:48 +03:00
Roman Artemev
cb130181a2 [Psi2Ir] Fix overridden symbols of Delegated Properties 2021-06-16 21:16:47 +03:00
Roman Artemev
32bbc3b8ad [KLIB] Fix SimpleTypeKey in case of type abbreviation 2021-06-16 21:16:46 +03:00
Roman Artemev
2f772c7a7c [KLIB] Add IrStatementOrigin into IrConstructorCall message 2021-06-16 21:16:45 +03:00
Roman Artemev
16ea3d9ae9 [TEST] Add IrText klib tests 2021-06-16 21:16:44 +03:00
Roman Artemev
14c91ca0de [TEST] Set proper TARGET_BACKEND for jvm-specific irText tests 2021-06-16 21:16:43 +03:00
Roman Golyshev
b587b71b0f FIR IDE: Move KtDeclarationAndFirDeclarationEqualityChecker.kt to nested api package 2021-06-16 15:38:57 +00:00
Roman Golyshev
c42fec5c93 FIR IDE: Refactor findSourceFirCompiledDeclaration
Add `FirDeclarationForCompiledElementSearcher` class to encapsulate
searching by the compiled declarations, move it to the separate file
2021-06-16 15:38:56 +00:00
Roman Golyshev
b0bac90a8b FIR IDE: Make findNonLocalDeclarationForCompiledElement a member of FirModuleResolveState 2021-06-16 15:38:56 +00:00
Roman Golyshev
e1f985424f FIR IDE: Move KtDeclarationAndFirDeclarationEqualityChecker to api package 2021-06-16 15:38:55 +00:00
Roman Golyshev
ad34c19f9a FIR IDE: Add explicit assertion that module info is ModuleSourceInfo 2021-06-16 15:38:54 +00:00
Roman Golyshev
44f74888e0 FIR IDE: Add tests for resolving compiled declarations
Also, use correct index to find source for properties in
`FirIdeDeserializedDeclarationSourceProvider` - this bug
was revealed by the tests
2021-06-16 15:38:53 +00:00
Roman Golyshev
0fe068c6ce FIR IDE: Find FIR declarations for compiled PSI elements separately
When PSI declaration comes from the library with classfiles,
its `moduleInfo` is represented by `LibrarySourceInfo` class.
In this case we have to resort to other ways of looking for
corresponding FIR declaration

It is easy to do for classes (by `classId`) and for the properties
(by `classId` of the containing class and property's name)

It is harder for callables, so we use
`KtDeclarationAndFirDeclarationEqualityChecker` to do that
2021-06-16 15:38:52 +00:00
Roman Golyshev
be51738483 FIR IDE: Move KtDeclarationAndFirDeclarationEqualityChecker to idea-fir-low-level-api module
It will be required to compare PSI and FIR declarations
for compiled PSI elements
2021-06-16 15:38:51 +00:00
Roman Golyshev
66047f159f FIR IDE: Resolve declaration in withFirDeclaration only if needed 2021-06-16 15:38:51 +00:00
Roman Golyshev
9e4c5eed5f FIR IDE: Make ModuleLibrariesSearchScope work only on .class sources
If this scope will accepts sources, then it will cause problems later
(when we will get libraries' sources from indices and will try to
resolve them to FIR declaration)
2021-06-16 15:38:50 +00:00
Igor Chevdar
caa852061a [box-tests] Ignored a test for K/N
More info in https://youtrack.jetbrains.com/issue/KT-44571
2021-06-16 17:25:07 +05:00
Abduqodiri Qurbonzoda
59031543e2 Throw on invalid AbstractMutableList.addAll index #KT-47211 2021-06-16 11:59:46 +00:00
Nikita Nazarov
7e44cddbab Introduce the fragment compiler backend to the debugger infrastructure 2021-06-16 13:58:18 +03:00
pyos
aa47191de4 JVM: hide ExpressionCodegen in finally block generation during inlining 2021-06-16 12:13:32 +02:00
pyos
108bd01698 JVM: refine the stack spilling around inline calls
Not all suspend functions need it - only those with suspension points.
2021-06-16 12:13:32 +02:00
pyos
b136acb185 JVM: move callSiteFile to InlineCallSiteInfo 2021-06-16 12:13:32 +02:00
pyos
6c1a5e1211 JVM: make inline function argument processing a bit shorter 2021-06-16 12:13:32 +02:00
pyos
392e4fba42 JVM: fix inlining of default lambdas of signature (Result) -> Any
They have no `invoke` bridge, and the overridden invoke expectes a boxed
`Result` as an argument.
2021-06-16 12:13:32 +02:00
pyos
a0a14d9e25 JVM: remove descriptors from SourceCompilerForInline
Printing the call site source on errors isn't really useful anyway - the
old backend points to a specific PsiElement, and JVM_IR wraps the
exception in FunctionCodegen (and printing the source never worked with
JVM_IR anyway).
2021-06-16 12:13:32 +02:00
pyos
32ad747632 JVM: load default lambda method nodes immediately
The ones that are not needed are filtered out before DefaultLambda is
even constructed anyway, and this way we need fewer lateinit vars.
2021-06-16 12:13:32 +02:00
pyos
1e953eaf01 JVM: remove contextKind from SourceCompilerForInline
Guess what? It's only useful for the old backend's type mapper!
2021-06-16 12:13:32 +02:00
pyos
1109348b6d JVM: remove lookupLocation from SourceCompilerForInline 2021-06-16 12:13:32 +02:00
pyos
b6e9f64e18 JVM: remove functionDescriptor from InlineCodegen 2021-06-16 12:13:32 +02:00
pyos
d89e2d9f08 JVM: split inline intrinsics into "needed by JVM_IR" and "not"
or, alternatively, "suspend" and "not".
2021-06-16 12:13:32 +02:00
pyos
eb4d831d27 JVM_IR: implement typeOf<T> as a codegen intrinsic
rather than a fake inline function.

Also, generate more correct instructions for typeOf. Not sure how that
even worked before - `aconst(Boolean)` isn't even valid.
2021-06-16 12:13:32 +02:00
pyos
7dbf08ae1c JVM: move loadCompiledInlineFunction out of InlineCodegen 2021-06-16 12:13:32 +02:00
pyos
8307367f90 JVM: don't thread callDefault through the inliner
It's only used by the old backend, and should be given to
PsiSourceCompilerForInline by PsiInlineCodegen.
2021-06-16 12:13:32 +02:00
sebastian.sellmair
6dd598c7a7 [Gradle] Enable Kotlin tooling metadata artifact by default
^KT-44584
2021-06-16 09:44:32 +00:00
Igor Chevdar
a1e5bef3ad [box-tests] Ignored some tests for K/N
A file included twice in a source set is not supported for now
2021-06-16 14:27:14 +05:00
Iaroslav Postovalov
0ba3ddcc29 Minor. Fix a typo, change visibility of internal object 2021-06-16 10:22:44 +03:00
Svyatoslav Scherbina
e324c9b3fb Generate initRuntimeIfNeeded() at the beginning of staticCFunction
#KT-44283 Fixed
2021-06-16 06:39:51 +00:00
Yaroslav Chernyshev
6e9739caec Add regression test for MPP android source set with resources 2021-06-16 09:32:45 +03:00
Georgy Bronnikov
f0f01db66e Temporarily mute a failing test 2021-06-16 01:48:28 +03:00
Ilya Kirillov
39e2df6916 FIR IDE: render unresolved types as qualifiers for member generator 2021-06-16 01:17:44 +03:00
Ilya Kirillov
cf7870e376 FIR IDE: implement toString for KtType 2021-06-16 01:17:43 +03:00
Ilya Kirillov
af9e6253e4 FIR IDE: add ability to specify type argument in KtClassTypeBuilder 2021-06-16 01:17:42 +03:00
Ilya Kirillov
148c90dd1e FIR IDE: do not make KtTypeArgumentWithVariance abstract
As it does not require specific FIR implementation
2021-06-16 01:17:41 +03:00
Ilya Kirillov
6a9c49dd9d FIR IDE: rename coneType parameter in KtFirType constructors to not accidentally leak it via lambdas 2021-06-16 01:17:40 +03:00
Ilya Kirillov
1d1eab6947 FIR IDE: make KtSymbolByFirBuilder to be a weak ref in KtType to avoid memory leaks 2021-06-16 01:17:39 +03:00
Ilya Kirillov
73bb2e76f2 FIR IDE: introduce KtFirDefinitelyNotNullType 2021-06-16 01:17:38 +03:00
Ilya Kirillov
8177a70ff9 FIR IDE: introduce KtCapturedType 2021-06-16 01:17:36 +03:00
Ilya Kirillov
e2cfd933f1 FIR IDE: introduce HL API for creating class types 2021-06-16 01:17:35 +03:00
Ilya Kirillov
8094a5448d FIR IDE: render error message for KtClassErrorType 2021-06-16 01:17:34 +03:00
Ilya Kirillov
0a6c96492a FIR IDE: simplify KtType hierarchy
- get rid of Kt(Non)DenotatbleType super classes as unused
- make KtErrorType to inherit KtClassType to be consistent with FIR
2021-06-16 01:17:32 +03:00
Tianyu Geng
f6078b24df FIR IDE: AddToString quickfix 2021-06-15 20:19:53 +02:00
Tianyu Geng
1b8b5b9a79 FIR IDE: move AddToStringFix to fe-independent 2021-06-15 20:19:52 +02:00
Tianyu Geng
4bedf41f9c FIR IDE: RemoveNulalbleFix quickfix 2021-06-15 20:19:52 +02:00
Tianyu Geng
b10de3dd2d FIR IDE: Move RemoveNullableFix to fe-independent 2021-06-15 20:19:52 +02:00
Victor Petukhov
559bedf5ae Continue processing not builder inference stub variables in the type checker during computing common super type
^KT-47148 Fixed
2021-06-15 17:40:56 +03:00
Victor Petukhov
85f4cec948 Don't ignore Java nullability annotations without target and unresolved when nullability qualifiers are extracted, with enabled type enhancement improvements
^KT-47276 Fixed
2021-06-15 17:28:25 +03:00
Mads Ager
ae03e2983d [JVM_IR] Keep track of catch variable gaps.
This ensures that catch variables are not visible in duplicated
finally blocks generated at an exit within the catch variable
scope.

^KT-46449 Fixed
2021-06-15 15:18:59 +02:00
Elena Lepilkina
6aba6ea670 [K/N][perf] Fix separator stayed wrong after migrating from groovy 2021-06-15 11:39:25 +00:00
Victor Petukhov
9fa0cf132f Regenerate idea fir low level api tests 2021-06-15 12:52:06 +03:00
Pavel Punegov
f9d5cc90a8 [native] Disable test that fail due to the unaligned int64 access 2021-06-15 11:51:43 +03:00
Vasily Levchenko
695339e21f [k/n][tests][debugger] test for KT-47198. 2021-06-15 08:04:19 +00:00
Vasily Levchenko
524a9351de [k/n][tests][debugger] modify test to conform KT-47198 2021-06-15 08:04:18 +00:00
Vasily Levchenko
81fd6126d9 [k/n][codegen][d/i] dont generate debug line information for prolog and {locals,stack}_init
- fixes KT-47198
2021-06-15 08:04:17 +00:00
Vasily Levchenko
bb42e601ab [k/n][tests][lldb] add quit to each lldb tests. 2021-06-15 08:04:17 +00:00
Victor Petukhov
1b82227308 Don't do new captured type specific checks for old ones in the type checker
^KT-47143 Fixed
2021-06-15 10:07:20 +03:00
Nikita Bobko
02a56a3077 [imltogradle] Fix 'Configuration with name 'compileOnlyApi' not found' 2021-06-14 16:56:55 +02:00
Nikita Bobko
ce0bef6b60 Update 211 platform version for Kotlin plugin 2021-06-14 16:56:55 +02:00
Nikita Bobko
3bf7eef4d8 [imltogradle] Generate maven repos based on 'jarRepositories.xml' from Community
This commit minimizes difference between build.gradle.kts
files generated from ultimate & community infrastructure
2021-06-14 16:56:55 +02:00
Jinseong Jeon
ce26d54917 FIR IDE: extract PsiType conversions to KtPsiTypeProvider 2021-06-13 00:10:47 +03:00
Jinseong Jeon
0db510ad8b FIR IDE/UAST: introduce UAST-specific version of analyse 2021-06-13 00:10:46 +03:00
Jinseong Jeon
1517fd0ca0 FIR/UAST: commonoize array access expression 2021-06-13 00:10:45 +03:00
Jinseong Jeon
ef8eddf1da FIR UAST: add array access tests 2021-06-13 00:10:44 +03:00
Jinseong Jeon
9a539aac7d FIR/UAST: commonize binary expression with type 2021-06-13 00:10:43 +03:00
Jinseong Jeon
b2e644b485 FIR/UAST: commonize type check expression 2021-06-13 00:10:41 +03:00
Jinseong Jeon
6e0f755b39 UAST: migrate kinds constants to the base module 2021-06-13 00:10:39 +03:00
Jinseong Jeon
47ede5bdc8 FIR IDE/UAST: get PsiType from KtTypeReference 2021-06-13 00:10:38 +03:00
Jinseong Jeon
a3710bed6a FIR/UAST: commonize type reference expression 2021-06-13 00:10:37 +03:00
Jinseong Jeon
517fd24f14 UAST: unify implementation/creation of type reference expression 2021-06-13 00:10:36 +03:00
Jinseong Jeon
fa36098214 FIR IDE/UAST: get PsiType from KtExpression 2021-06-13 00:10:34 +03:00
Ilya Kirillov
7d7782e8ff Fix FE1.0 intention test 2021-06-12 23:53:46 +03:00
Mark Punzalan
235f4200df FIR IDE: Add descriptions for HLAddAccessorIntentions (copied from FE
1.0 implementations).
2021-06-12 23:53:45 +03:00
Mark Punzalan
9b5f754e75 FIR IDE: Enable add accessors quickfix for MUST_BE_INITIALIZED.
Also added diagnosticFixFactoriesFromIntentionActions() to share
quickfix-creation across multiple diagnostics with the same PSI.
2021-06-12 23:53:44 +03:00
Mark Punzalan
cd6dbd2515 FIR IDE: Assert that the action to invoke in
AbstractHighLevelQuickFixTest is of type QuickFixActionBase.
2021-06-12 23:53:43 +03:00
Mark Punzalan
783e5972d0 FIR IDE: Ensure all fixes provided by HLDiagnosticFixFactory are of type
QuickFixActionBase.

This allows us to verify in the quickfix tests that the action comes
from a diagnostic-based quickfix, and not an available intention. We
are adding APIs that wrap IntentionActions as QuickFixActionBase.
2021-06-12 23:53:42 +03:00
Mark Punzalan
43a8299f48 FIR IDE: Delete AddAccessorsIntention in favor of
HLAddAccessorIntentions.
2021-06-12 23:53:41 +03:00
Mark Punzalan
91e62832ee FIR IDE: Add applicability range to HLAddAccessorIntention (copied from
FE 1.0's logic) and actually check the range in AbstractHLIntention.
2021-06-12 23:53:40 +03:00
Mark Punzalan
a497dd1d31 FIR IDE: Enable add accessor intentions in plugin. 2021-06-12 23:53:39 +03:00
Ilya Kirillov
4f12966d66 FIR IDE: warn about enabled Android plugin 2021-06-12 19:40:43 +03:00
Ilya Kirillov
af7766b3ac FIR IDE: add fir icon to status bar to distinguish fir/fe10 ide 2021-06-12 19:40:42 +03:00
Jinseong Jeon
8977e7766b FIR/UAST: commonize throw expression 2021-06-12 16:00:43 +02:00
Jinseong Jeon
c21fce6cbc FIR/UAST: commonize parenthesized expression 2021-06-12 16:00:42 +02:00
Jinseong Jeon
c089b8ed04 FIR/UAST: commonize labeled expression 2021-06-12 16:00:41 +02:00
Jinseong Jeon
6e1b04e4c9 FIR/UAST: commonize if expression 2021-06-12 16:00:40 +02:00
Jinseong Jeon
50f750187b FIR/UAST: commonize loop/break/continue expressions 2021-06-12 16:00:39 +02:00
Jinseong Jeon
1146f60db3 FIR/UAST: commonize block and return expressions 2021-06-12 16:00:37 +02:00
Jinseong Jeon
16b3d2110e FIR/UAST: commonize literal expressions 2021-06-12 16:00:36 +02:00
Jinseong Jeon
6b5bddeed7 FIR/UAST: commonize KotlinEvaluatableUElement 2021-06-12 16:00:35 +02:00
Jinseong Jeon
ce10410aba FIR UAST: refactor FE1 UAST tests 2021-06-12 16:00:34 +02:00
Jinseong Jeon
e1a99ede09 FIR UAST: introduce values tests 2021-06-12 16:00:32 +02:00
Jinseong Jeon
cf2f36fa49 UAST: utilize values test base 2021-06-12 16:00:31 +02:00
Jinseong Jeon
d17dd4a1e6 FIR/UAST: commonize KotlinUElementWithType 2021-06-12 16:00:30 +02:00
Jinseong Jeon
1025851edd FIR UAST: introduce types tests 2021-06-12 16:00:29 +02:00
Jinseong Jeon
6afb68cec0 UAST: utilize types test base 2021-06-12 16:00:28 +02:00
Vyacheslav Gerasimov
06b4fe1613 Build: Fix kotlin-stdlib-jvm-minimal-for-test usages
Name changed after publishing with main artifacts for external usage
2021-06-12 04:33:32 +03:00
Steffi Stumpos
8baf570ee7 Build: Publish the new compiler test infrastructure 2021-06-12 04:33:31 +03:00
Mikhail Glukhikh
af5e2f3c93 FIR checkers: properly handle annotations with more than one argument 2021-06-11 22:03:33 +03:00
Mikhail Glukhikh
ceb527c5e4 FIR: add OptIn checkers draft + some annotation / SinceKotlin utilities 2021-06-11 22:03:32 +03:00
Mikhail Glukhikh
bd39e457a7 FIR: make ArrayMapOwner.arrayMap really protected 2021-06-11 22:03:32 +03:00
Mikhail Glukhikh
0972020324 Extract common parts from ExperimentalUsageChecker 2021-06-11 22:03:32 +03:00
Mikhail Glukhikh
f0453d2f5c FIR: distinguish qualified access / qualified access expression checkers 2021-06-11 22:03:32 +03:00
Mads Ager
6b6ba77869 [JVM_IR] Trim the expression test string for null assertions.
^KT-47166 Fixed.
2021-06-11 21:54:04 +03:00
Alexander Shabalin
58adfd8488 Disable enum and object isFrozen tests on wasm 2021-06-11 18:12:15 +00:00
Roman Golyshev
3f0cc67f17 Fix converting string GLOB to regexp in TestConfigurationBuilder
This is required when `p1|p2|p3|...|pN` concatenation is used (see `or`
extension function above `toMatchingRegexString`)

This is a follow-up to the 6f4b6c1b5b7bc05557306179e25a79fa234aa77f
commit
2021-06-11 20:06:04 +03:00
Roman Golyshev
30f20cb835 Use more reliable paths matching in TestConfigurationBuilder
Without it, even the slightest difference between the pattern and
testDataPath would cause the path to be excluded, for example:

testDataPath = /some/absolute/path.txt
pattern = absolute/*

The example above didn't match, and it resulted in different
configurations when tests were launched with different testDataPaths

Now, the example above will look like this:

testDataPath = /some/absolute/path.txt
patter = */absolute/*

Now it matches correctly
2021-06-11 20:06:03 +03:00
nataliya.valtman
d42a6771b0 Update statistics that should be sent to ES
Next properties should be set in gradle.properties or via -D option:
systemProp.kotlin.plugin.stat.password
systemProp.kotlin.plugin.stat.user
systemProp.kotlin.plugin.stat.enabled=true
systemProp.kotlin.plugin.stat.label
systemProp.kotlin.plugin.stat.endpoint=es_endpoint/index/_doc
kotlin.build.report.verbose=true
kotlin.build.report.enable=true
2021-06-11 19:12:05 +03:00
Dmitry Petrov
bf077b893c PSI2IR KT-47245 handle declaration statements in control structures 2021-06-11 16:42:31 +03:00
pyos
3be348f910 JVM_IR: fix parentClassId for property accessors 2021-06-11 15:03:13 +02:00
pyos
d4485bc475 JVM: remove unused methodOwner from InlineCodegen 2021-06-11 15:03:13 +02:00
pyos
ed26e97df8 JVM: refactor loading of inline functions from binaries
The IR path no longer does any descriptor unwrapping or old-style type
mapping.
2021-06-11 15:03:13 +02:00
pyos
7bcd738bb1 JVM: inline createInlineMethodNode into InlineCodegenForDefaultBody
Most of it is unused, since there we know the target function will also
need to be compiled from source.
2021-06-11 15:03:13 +02:00
pyos
4c7eb815fc JVM: remove some FunctionDescriptors from SourceCompilerForInline 2021-06-11 15:03:13 +02:00
pyos
a24ad233ee JVM: move PsiSourceCompilerForInline to a separate file 2021-06-11 15:03:13 +02:00
pyos
955b9260d1 JVM: move more old backend code out of InlineCodegen 2021-06-11 15:03:13 +02:00
pyos
043452fb62 JVM: make handling of captured params for default lambdas shorter 2021-06-11 15:03:13 +02:00
pyos
4cae880b44 JVM: remove unused DefaultLambda.parameterOffsetsInDefault 2021-06-11 15:03:13 +02:00
pyos
8a3af851d9 JVM: pregenerate inline lambda bodies as early as possible
Which in JVM_IR is immediately in `genValueAndPut`, but for the old
backend needs to be delayed until `genCallInner` for some reason.
2021-06-11 15:03:13 +02:00
pyos
90412ade8a JVM: remove second parameter of putClosureParametersOnStack
Only used by the old backend.
2021-06-11 15:03:13 +02:00
pyos
d4c8a033b1 JVM: remove BaseExpressionCodegen.pushClosureOnStack
It's only used by the old backend
2021-06-11 15:03:13 +02:00
pyos
b6c3c9942d JVM: move activeLambda to PsiInlineCodegen 2021-06-11 15:03:13 +02:00
pyos
7333abf50d JVM: purge redundant val BaseExpressionCodegen.v 2021-06-11 15:03:13 +02:00
pyos
1f9db7cf25 FE: properly clear the deferred generator stack
Before this commit the stack wasn't cleared for read variable case.
#KT-47168 Fixed
2021-06-11 15:56:20 +03:00
Sergey Bogolepov
2f632ada42 [Native] Remove unused code 2021-06-11 12:18:15 +00:00
Sergey Bogolepov
36386de9a2 [Native] Drop explicit -fPIC flag setup
We don't need to explicitly set -fPIC flag everywhere
because since d82109cc92
it is set by default for all ClangArgs users.
2021-06-11 12:18:14 +00:00
Sergey Bogolepov
7550351702 [Native] Fix runtime code according to Clang 11 warnings 2021-06-11 12:17:00 +00:00
Georgy Bronnikov
91387e644f IR: repair collectAndFilterRealOverrides 2021-06-11 15:05:45 +03:00
Georgy Bronnikov
7e6782d684 JVM_IR: simplify resolveFakeOverride call in SyntheticAccessorLowering 2021-06-11 15:05:45 +03:00
Georgy Bronnikov
fca804de14 IR: properly compute IrProperty.resolveFakeOverride()
Now that IrProperty has its own overriddenSymbols, we can generalize the
search for fake overrides. Also works for fake override properties
derived from Java fields.
2021-06-11 15:05:45 +03:00
Jinseong Jeon
3769fd8e07 FIR UAST: fix import resolve test
The `resolve` failure (or `null` return) of import directive for
`java.lang.Thread.sleep` is legitimate, since there are two static methods
in `java.lang.Thread`:
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Thread.html
hence not able to resolve to a single method.

Unless we change `UImportStatement` to be a subtype of `UMultiResolvable`,
instead of `UResolvable`, we can't properly test `resolve` API for that.
2021-06-11 14:51:07 +03:00
Yahor Berdnikau
da25d58fa7 Control cache redirector status in test via project settings.
Test will use project `gradle.properties` file to get current
cache redirector status, so it could be controlled from one place.

^KT-47185 Fixed
2021-06-11 11:44:36 +00:00
Yahor Berdnikau
7b1db6992e Enable cache redirector for old tests setup.
^KT-47185 Fixed
2021-06-11 11:44:35 +00:00
Yahor Berdnikau
e98de36aaa Enable cache redirector for Junit5 tests.
^KT-47185 In Progress
2021-06-11 11:44:34 +00:00
Yahor Berdnikau
5d0abf0e33 Lazily apply cache redirector to all project modules.
Mainly move it from 'afterEvaluate { .. }' block.

^KT-47185 In Progress
2021-06-11 11:44:34 +00:00
Viacheslav Kormushkin
3c0709cf4f A new DSL for framework configuration within cocoapods block
#KT-46479
#KT-35723
2021-06-11 11:10:49 +00:00
Mikhail Glukhikh
5a3f84c8fa Add forgotten test data file 2021-06-11 13:17:01 +03:00
Svyatoslav Scherbina
b13e7d1e28 Native: enable more Obj-C interop tests for new MM 2021-06-11 07:35:50 +00:00
Svyatoslav Scherbina
79d4047e86 Native: improve thread state switching for Obj-C interop 2021-06-11 07:35:49 +00:00
Svyatoslav Scherbina
85ab4f68df Native: support reentrant mode for CalledFromNativeGuard 2021-06-11 07:35:48 +00:00
sebastian.sellmair
1bcafd3cd0 [Gradle] commonizeCInterop task: Require hierarchical commonization to be enabled
^KT-47133 Verification Pending
2021-06-11 07:03:24 +00:00
Roman Golyshev
d781902626 Add possibility to use baseDir in SpecHelpersSourceFilesProvider
In IJ infrastructure we have specific path prefix for compiler testData
2021-06-11 02:28:39 +03:00
Vladimir Dolzhenko
2c8d583d8b Added ad-hoc KtValueArgument.stringTemplateExpression
Use only stub stringTemplateExpression if it is present and don't use ast nodes as it could be unbounded

#KT-47034 Fixed
2021-06-10 21:14:32 +00:00
53584 changed files with 134912 additions and 1197078 deletions

3
.bunch
View File

@@ -1,2 +1,3 @@
202
as42
203_202
as42

8
.idea/dictionaries/igor.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<component name="ProjectDictionaryState">
<dictionary name="igor">
<words>
<w>descr</w>
<w>exprs</w>
</words>
</dictionary>
</component>

View File

@@ -2,6 +2,7 @@
<dictionary name="skuzmich">
<words>
<w>anyref</w>
<w>dataref</w>
<w>ushr</w>
<w>wasm</w>
</words>

View File

@@ -11,7 +11,7 @@
<option name="taskNames">
<list>
<option value=":compiler:fir:checkers:generateCheckersComponents" />
<option value=":idea:idea-frontend-fir:generateCode" />
<option value=":idea-frontend-fir:generateCode" />
</list>
</option>
<option name="vmOptions" value="" />

View File

@@ -1,20 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA" type="GradleRunConfiguration" factoryName="Gradle" singleton="true" folderName="IDEA">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runIde" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<method />
</configuration>
</component>

View File

@@ -1,20 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA Ultimate" type="GradleRunConfiguration" factoryName="Gradle" folderName="IDEA">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-P intellijUltimateEnabled" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runUltimate" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<method />
</configuration>
</component>

View File

@@ -1,20 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA Ultimate (No ProcessCanceledException) " type="GradleRunConfiguration" factoryName="Gradle" folderName="IDEA">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-PnoPCE" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runUltimate" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<method />
</configuration>
</component>

View File

@@ -1,20 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA (No ProcessCanceledException)" type="GradleRunConfiguration" factoryName="Gradle" folderName="IDEA">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-PnoPCE" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runIde" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<method />
</configuration>
</component>

View File

@@ -1,19 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA (Not Internal)" type="GradleRunConfiguration" factoryName="Gradle" folderName="IDEA">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-Pidea.is.internal=false" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runIde" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
</configuration>
</component>

View File

@@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Test: Commonizer / Light" type="GradleRunConfiguration" factoryName="Gradle" folderName="Tests">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":native:kotlin-klib-commonizer-api:test" />
<option value=":native:kotlin-klib-commonizer:test" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

File diff suppressed because it is too large Load Diff

View File

@@ -35,26 +35,30 @@ Support for multiplatform programming is one of Kotlins key benefits. It redu
## Editing Kotlin
* [Kotlin IntelliJ IDEA Plugin](https://kotlinlang.org/docs/tutorials/getting-started.html)
* [Kotlin IntelliJ IDEA Plugin](https://kotlinlang.org/docs/tutorials/getting-started.html) ([source code](https://github.com/JetBrains/intellij-community/tree/master/plugins/kotlin))
* [Kotlin Eclipse Plugin](https://kotlinlang.org/docs/tutorials/getting-started-eclipse.html)
* [Kotlin Sublime Text Package](https://github.com/vkostyukov/kotlin-sublime-package)
## Build environment requirements
In order to build Kotlin distribution you need to have:
This repository is using [Gradle toolchains](https://docs.gradle.org/current/userguide/toolchains.html) feature
to select and auto-provision required JDKs from [AdoptOpenJdk](https://adoptopenjdk.net) project.
- JDK 1.6, 1.7, 1.8 and 9
- Setup environment variables as following:
Unfortunately [AdoptOpenJdk](https://adoptopenjdk.net) project does not provide required JDK 1.6 and 1.7 images,
so you could either download them manually and provide path to installation via `JDK_16` and `JDK_17` environment variables or
use following SDK managers:
- [Asdf-vm](https://asdf-vm.com/)
- [Jabba](https://github.com/shyiko/jabba)
- [SDKMAN!](https://sdkman.io/)
JAVA_HOME="path to JDK 1.8"
JDK_16="path to JDK 1.6"
JDK_17="path to JDK 1.7"
JDK_18="path to JDK 1.8"
JDK_9="path to JDK 9"
Alternatively, it is still possible to only provide required JDKs via environment variables
(see [gradle.properties](./gradle.properties#L5) for supported variable names). To ensure Gradle uses only JDKs
from environmental variables - disable Gradle toolchain auto-detection by passing `-Porg.gradle.java.installations.auto-detect=false` option
(or put it into `$GRADLE_USER_HOME/gradle.properties`).
For local development, if you're not working on bytecode generation or the standard library, it's OK to have only JDK 1.8 and JDK 9 installed, and to point `JDK_16` and `JDK_17` environment variables to your JDK 1.8 installation.
You also can use [Gradle properties](https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties) to setup `JDK_*` variables.
For local development, if you're not working on bytecode generation or the standard library, it's OK to avoid installing JDK 1.6 and JDK 1.7.
Add `kotlin.build.isObsoleteJdkOverrideEnabled=true` to the `local.properties` file, so build will only use JDK 1.8+. Note, that in this
case, build will have Gradle remote build cache misses for some tasks.
Note: The JDK 6 for MacOS is not available on Oracle's site. You can install it by
@@ -93,13 +97,10 @@ command line parameters on the first run:
- `clean` - clean build results
- `dist` - assembles the compiler distribution into `dist/kotlinc/` folder
- `ideaPlugin` - assembles the Kotlin IDEA plugin distribution into `dist/artifacts/ideaPlugin/Kotlin/` folder
- `install` - build and install all public artifacts into local maven repository
- `runIde` - build IDEA plugin and run IDEA with it
- `coreLibsTest` - build and run stdlib, reflect and kotlin-test tests
- `gradlePluginTest` - build and run gradle plugin tests
- `compilerTest` - build and run all compiler tests
- `ideaPluginTest` - build and run all IDEA plugin tests
To reproduce TeamCity build use `-Pteamcity=true` flag. Local builds don't run proguard and have jar compression disabled by default.
@@ -139,14 +140,6 @@ To be able to run tests from IntelliJ easily, check `Delegate IDE build/run acti
At this time, you can use the latest released `1.3.x` version of the Kotlin plugin for working with the code. To make sure you have the latest version installed, use `Tools` -> `Kotlin` -> `Configure Kotlin Plugin Updates`.
### Compiling and running
From this root project there are Run/Debug Configurations for running `IDEA` or the `Generate Compiler Tests` for example; so if you want to try out the latest and greatest IDEA plugin
* `VCS` -> `Git` -> `Pull`
* Run the `IDEA` run configuration in the project
* A child IntelliJ IDEA with the Kotlin plugin will then startup
### Dependency verification
We have a [dependencies verification](https://docs.gradle.org/current/userguide/dependency_verification.html) feature enabled in the

View File

@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.context.withModule
import org.jetbrains.kotlin.context.withProject
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.builder.PsiHandlingMode
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.createSessionForTests
import org.jetbrains.kotlin.fir.java.FirJavaElementFinder
@@ -154,7 +155,7 @@ abstract class AbstractSimpleFileBenchmark {
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(env.project))
val session = createSessionForTests(env, scope)
val firProvider = session.firProvider as FirProviderImpl
val builder = RawFirBuilder(session, firProvider.kotlinScopeProvider)
val builder = RawFirBuilder(session, firProvider.kotlinScopeProvider, PsiHandlingMode.COMPILER)
val totalTransformer = FirTotalResolveProcessor(session)
val firFile = builder.buildFirFile(file).also(firProvider::recordFile)

View File

@@ -40,7 +40,7 @@ abstract class BuildMetaInfoFactory<T : BuildMetaInfo>(private val metaInfoClass
): T
fun create(args: CommonCompilerArguments): T {
val languageVersion = args.languageVersion?.let((LanguageVersion)::fromVersionString) ?: LanguageVersion.LATEST_STABLE
val languageVersion = args.languageVersion?.let { LanguageVersion.fromVersionString(it) } ?: LanguageVersion.LATEST_STABLE
return create(
isEAP = languageVersion.isPreRelease(),
@@ -51,7 +51,7 @@ abstract class BuildMetaInfoFactory<T : BuildMetaInfo>(private val metaInfoClass
ownVersion = OWN_VERSION,
coroutinesVersion = COROUTINES_VERSION,
multiplatformVersion = MULTIPLATFORM_VERSION,
metadataVersionArray = args.metadataVersion?.let((BinaryVersion)::parseVersionArray)
metadataVersionArray = args.metadataVersion?.let { BinaryVersion.parseVersionArray(it) }
)
}

View File

@@ -17,6 +17,7 @@ enum class BuildAttributeKind : Serializable {
enum class BuildAttribute(val kind: BuildAttributeKind) : Serializable {
NO_BUILD_HISTORY(BuildAttributeKind.REBUILD_REASON),
NO_ABI_SNAPSHOT(BuildAttributeKind.REBUILD_REASON),
CACHE_CORRUPTION(BuildAttributeKind.REBUILD_REASON),
UNKNOWN_CHANGES_IN_GRADLE_INPUTS(BuildAttributeKind.REBUILD_REASON),
JAVA_CHANGE_UNTRACKED_FILE_IS_REMOVED(BuildAttributeKind.REBUILD_REASON),

View File

@@ -9,6 +9,7 @@ import java.io.Serializable
@Suppress("Reformat")
enum class BuildTime(val parent: BuildTime? = null) : Serializable {
GRADLE_TASK_ACTION,
GRADLE_TASK,
CLEAR_OUTPUT(GRADLE_TASK),
BACKUP_OUTPUT(GRADLE_TASK),
@@ -20,6 +21,10 @@ enum class BuildTime(val parent: BuildTime? = null) : Serializable {
NON_INCREMENTAL_COMPILATION_OUT_OF_PROCESS(RUN_COMPILER),
NON_INCREMENTAL_COMPILATION_DAEMON(RUN_COMPILER),
INCREMENTAL_COMPILATION(RUN_COMPILER),
STORE_BUILD_INFO(INCREMENTAL_COMPILATION),
JAR_SNAPSHOT(INCREMENTAL_COMPILATION),
SET_UP_ABI_SNAPSHOTS(JAR_SNAPSHOT),
IC_ANALYZE_JAR_FILES(JAR_SNAPSHOT),
IC_CALCULATE_INITIAL_DIRTY_SET(INCREMENTAL_COMPILATION),
IC_ANALYZE_CHANGES_IN_DEPENDENCIES(IC_CALCULATE_INITIAL_DIRTY_SET),
IC_FIND_HISTORY_FILES(IC_ANALYZE_CHANGES_IN_DEPENDENCIES),

View File

@@ -30,6 +30,28 @@ class ChangesCollector {
private val changedMembers = hashMapOf<FqName, MutableSet<String>>()
private val areSubclassesAffected = hashMapOf<FqName, Boolean>()
//TODO for test only: ProtoData or ProtoBuf
private val storage = hashMapOf<FqName, ProtoData>()
private val removed = ArrayList<FqName>()
//TODO change to immutable map
fun protoDataChanges(): Map<FqName, ProtoData> = storage
fun protoDataRemoved(): List<FqName> = removed
companion object {
fun <T> T.getNonPrivateNames(nameResolver: NameResolver, vararg members: T.() -> List<MessageLite>) =
members.flatMap { this.it().filterNot { it.isPrivate }.names(nameResolver) }.toSet()
fun ClassProtoData.getNonPrivateMemberNames(): Set<String> {
return proto.getNonPrivateNames(
nameResolver,
ProtoBuf.Class::getConstructorList,
ProtoBuf.Class::getFunctionList,
ProtoBuf.Class::getPropertyList
) + proto.enumEntryList.map { nameResolver.getString(it.name) }
}
}
fun changes(): List<ChangeInfo> {
val changes = arrayListOf<ChangeInfo>()
@@ -57,7 +79,7 @@ class ChangesCollector {
}
private fun <T, R> MutableMap<T, MutableSet<R>>.getSet(key: T) =
getOrPut(key) { HashSet() }
getOrPut(key) { HashSet() }
private fun collectChangedMember(scope: FqName, name: String) {
changedMembers.getSet(scope).add(name)
@@ -79,11 +101,35 @@ class ChangesCollector {
}
}
fun collectProtoChanges(oldData: ProtoData?, newData: ProtoData?, collectAllMembersForNewClass: Boolean = false) {
fun collectProtoChanges(oldData: ProtoData?, newData: ProtoData?, collectAllMembersForNewClass: Boolean = false, packageProtoKey: String? = null) {
if (oldData == null && newData == null) {
throw IllegalStateException("Old and new value are null")
}
if (newData != null) {
when (newData) {
is ClassProtoData -> {
val fqName = newData.nameResolver.getClassId(newData.proto.fqName).asSingleFqName()
storage[fqName] = newData
}
is PackagePartProtoData -> {
//TODO fqName is not unique. It's package and can be present in both java and kotlin
val fqName = newData.packageFqName
storage[packageProtoKey?.let { FqName(it) } ?: fqName] = newData
}
}
} else if (oldData != null) {
when (oldData) {
is ClassProtoData -> {
removed.add(oldData.nameResolver.getClassId(oldData.proto.fqName).asSingleFqName())
}
is PackagePartProtoData -> {
//TODO fqName is not unique. It's package and can be present in both java and kotlin
removed.add(packageProtoKey?.let { FqName(it) } ?: oldData.packageFqName)
}
}
}
if (oldData == null) {
newData!!.collectAll(isRemoved = false, isAdded = true, collectAllMembersForNewClass = collectAllMembersForNewClass)
return
@@ -125,8 +171,8 @@ class ChangesCollector {
}
}
private fun <T> T.getNonPrivateNames(nameResolver: NameResolver, vararg members: T.() -> List<MessageLite>): Set<String> =
members.flatMap { this.it().filterNot { it.isPrivate }.names(nameResolver) }.toSet()
fun <T> T.getNonPrivateNames(nameResolver: NameResolver, vararg members: T.() -> List<MessageLite>) =
members.flatMap { this.it().filterNot { it.isPrivate }.names(nameResolver) }.toSet()
//TODO remember all sealed parent classes
private fun ProtoData.collectAll(isRemoved: Boolean, isAdded: Boolean, collectAllMembersForNewClass: Boolean = false) =
@@ -137,16 +183,15 @@ class ChangesCollector {
private fun PackagePartProtoData.collectAllFromPackage(isRemoved: Boolean) {
val memberNames =
proto.getNonPrivateNames(
nameResolver,
ProtoBuf.Package::getFunctionList,
ProtoBuf.Package::getPropertyList
)
proto.getNonPrivateNames(
nameResolver,
ProtoBuf.Package::getFunctionList,
ProtoBuf.Package::getPropertyList
)
if (isRemoved) {
collectRemovedMembers(packageFqName, memberNames)
}
else {
} else {
collectChangedMembers(packageFqName, memberNames)
}
}
@@ -161,8 +206,7 @@ class ChangesCollector {
val collectMember = if (isRemoved) this@ChangesCollector::collectRemovedMember else this@ChangesCollector::collectChangedMember
collectMember(classFqName.parent(), classFqName.shortName().asString())
memberNames.forEach { collectMember(classFqName, it) }
}
else {
} else {
if (!isRemoved && collectAllMembersForNewClass) {
val memberNames = getNonPrivateMemberNames()
memberNames.forEach { this@ChangesCollector.collectChangedMember(classFqName, it) }
@@ -189,15 +233,6 @@ class ChangesCollector {
addChangedParents(fqName, changedParentsFqNames)
}
private fun ClassProtoData.getNonPrivateMemberNames(): Set<String> {
return proto.getNonPrivateNames(
nameResolver,
ProtoBuf.Class::getConstructorList,
ProtoBuf.Class::getFunctionList,
ProtoBuf.Class::getPropertyList
) + proto.enumEntryList.map { nameResolver.getString(it.name) }
}
fun collectMemberIfValueWasChanged(scope: FqName, name: String, oldValue: Any?, newValue: Any?) {
if (oldValue == null && newValue == null) {
throw IllegalStateException("Old and new value are null for $scope#$name")
@@ -205,8 +240,7 @@ class ChangesCollector {
if (oldValue != null && newValue == null) {
collectRemovedMember(scope, name)
}
else if (oldValue != newValue) {
} else if (oldValue != newValue) {
collectChangedMember(scope, name)
}
}

View File

@@ -0,0 +1,76 @@
/*
* 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.incremental
import org.jetbrains.kotlin.name.FqName
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.io.Serializable
/**
* Changes to the classpath of the `KotlinCompile` task, used to compute the source files that need to be recompiled during an incremental
* run.
*/
sealed class ClasspathChanges : Serializable {
class Available() : ClasspathChanges() {
lateinit var lookupSymbols: List<LookupSymbol>
private set
lateinit var fqNames: List<FqName>
private set
constructor(lookupSymbols: List<LookupSymbol>, fqNames: List<FqName>) : this() {
this.lookupSymbols = lookupSymbols
this.fqNames = fqNames
}
private fun writeObject(out: ObjectOutputStream) {
out.writeInt(lookupSymbols.size)
lookupSymbols.forEach {
out.writeUTF(it.name)
out.writeUTF(it.scope)
}
out.writeInt(fqNames.size)
fqNames.forEach {
out.writeUTF(it.asString())
}
}
private fun readObject(ois: ObjectInputStream) {
val lookupSymbolsSize = ois.readInt()
val lookupSymbols = ArrayList<LookupSymbol>(lookupSymbolsSize)
repeat(lookupSymbolsSize) {
val name = ois.readUTF()
val scope = ois.readUTF()
lookupSymbols.add(LookupSymbol(name, scope))
}
this.lookupSymbols = lookupSymbols
val fqNamesSize = ois.readInt()
val fqNames = ArrayList<FqName>(fqNamesSize)
repeat(fqNamesSize) {
val fqNameString = ois.readUTF()
fqNames.add(FqName(fqNameString))
}
this.fqNames = fqNames
}
companion object {
private const val serialVersionUID = 0L
}
}
sealed class NotAvailable : ClasspathChanges() {
object UnableToCompute : NotAvailable()
object ForNonIncrementalRun : NotAvailable()
object ClasspathSnapshotIsDisabled : NotAvailable()
object ReservedForTestsOnly : NotAvailable()
object ForJSCompiler : NotAvailable()
}
}

View File

@@ -137,8 +137,8 @@ open class IncrementalJsCache(
}
for ((srcFile, irData) in incrementalResults.irFileData) {
val (fileData, types, signatures, strings, declarations, bodies, fqn) = irData
irTranslationResults.put(srcFile, fileData, types, signatures, strings, declarations, bodies, fqn)
val (fileData, types, signatures, strings, declarations, bodies, fqn, debugInfos) = irData
irTranslationResults.put(srcFile, fileData, types, signatures, strings, declarations, bodies, fqn, debugInfos)
}
}
@@ -269,6 +269,7 @@ private object IrTranslationResultValueExternalizer : DataExternalizer<IrTransla
output.writeArray(value.declarations)
output.writeArray(value.bodies)
output.writeArray(value.fqn)
value.debugInfo?.let { output.writeArray(it) }
}
private fun DataOutput.writeArray(array: ByteArray) {
@@ -283,6 +284,17 @@ private object IrTranslationResultValueExternalizer : DataExternalizer<IrTransla
return filedata
}
private fun DataInput.readArrayOrNull(): ByteArray? {
try {
val dataSize = readInt()
val filedata = ByteArray(dataSize)
readFully(filedata)
return filedata
} catch (e: Throwable) {
return null
}
}
override fun read(input: DataInput): IrTranslationResultValue {
val fileData = input.readArray()
val types = input.readArray()
@@ -291,8 +303,9 @@ private object IrTranslationResultValueExternalizer : DataExternalizer<IrTransla
val declarations = input.readArray()
val bodies = input.readArray()
val fqn = input.readArray()
val debugInfos = input.readArrayOrNull()
return IrTranslationResultValue(fileData, types, signatures, strings, declarations, bodies, fqn)
return IrTranslationResultValue(fileData, types, signatures, strings, declarations, bodies, fqn, debugInfos)
}
}
@@ -317,10 +330,11 @@ private class IrTranslationResultMap(
newStrings: ByteArray,
newDeclarations: ByteArray,
newBodies: ByteArray,
fqn: ByteArray
fqn: ByteArray,
debugInfos: ByteArray?
) {
storage[pathConverter.toPath(sourceFile)] =
IrTranslationResultValue(newFiledata, newTypes, newSignatures, newStrings, newDeclarations, newBodies, fqn)
IrTranslationResultValue(newFiledata, newTypes, newSignatures, newStrings, newDeclarations, newBodies, fqn, debugInfos)
}
operator fun get(sourceFile: File): IrTranslationResultValue? =

View File

@@ -185,7 +185,7 @@ open class IncrementalJvmCache(
sourceToClassesMap.add(source, jvmClassName)
val (proto, nameResolver) = serializedJavaClass.toProtoData()
addToClassStorage(proto, nameResolver, source)
// collector.addJavaProto(ClassProtoData(proto, nameResolver))
dirtyOutputClassesMap.notDirty(jvmClassName)
}
@@ -308,7 +308,7 @@ open class IncrementalJvmCache(
storage[key] = newData
val packageFqName = kotlinClass.className.packageFqName
changesCollector.collectProtoChanges(oldData?.toProtoData(packageFqName), newData.toProtoData(packageFqName))
changesCollector.collectProtoChanges(oldData?.toProtoData(packageFqName), newData.toProtoData(packageFqName), packageProtoKey = key)
}
operator fun contains(className: JvmClassName): Boolean =

View File

@@ -12,7 +12,8 @@ data class IncrementalModuleEntry(
private val projectPath: String,
val name: String,
val buildDir: File,
val buildHistoryFile: File
val buildHistoryFile: File,
val abiSnapshot: File
) : Serializable {
companion object {
private const val serialVersionUID = 0L
@@ -26,7 +27,9 @@ class IncrementalModuleInfo(
val nameToModules: Map<String, Set<IncrementalModuleEntry>>,
val jarToClassListFile: Map<File, File>,
// only for js and mpp
val jarToModule: Map<File, IncrementalModuleEntry>
val jarToModule: Map<File, IncrementalModuleEntry>,
//for JVM only
val jarToAbiSnapshot: Map<File, File>
) : Serializable {
companion object {
private const val serialVersionUID = 1L

View File

@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.incremental
import com.intellij.openapi.diagnostic.Logger
import com.intellij.util.containers.MultiMap
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -33,6 +34,8 @@ open class LookupStorage(
targetDataDir: File,
pathConverter: FileToPathConverter
) : BasicMapsOwner(targetDataDir) {
val LOG = Logger.getInstance("#org.jetbrains.kotlin.jps.build.KotlinBuilder")
companion object {
private val DELETED_TO_SIZE_TRESHOLD = 0.5
private val MINIMUM_GARBAGE_COLLECTIBLE_SIZE = 10000
@@ -41,36 +44,44 @@ open class LookupStorage(
private val countersFile = "counters".storageFile
private val idToFile = registerMap(IdToFileMap("id-to-file".storageFile, pathConverter))
private val fileToId = registerMap(FileToIdMap("file-to-id".storageFile, pathConverter))
private val lookupMap = registerMap(LookupMap("lookups".storageFile))
val lookupMap = registerMap(LookupMap("lookups".storageFile))
@Volatile
private var size: Int = 0
@Volatile
private var deletedCount: Int = 0
init {
try {
if (countersFile.exists()) {
val lines = countersFile.readLines()
size = lines[0].toInt()
deletedCount = lines[1].toInt()
}
} catch (e: Exception) {
throw IOException("Could not read $countersFile", e)
}
}
@Synchronized
fun get(lookupSymbol: LookupSymbol): Collection<String> {
val key = LookupSymbolKey(lookupSymbol.name, lookupSymbol.scope)
val fileIds = lookupMap[key] ?: return emptySet()
val paths = mutableSetOf<String>()
val filtered = mutableSetOf<Int>()
for (fileId in fileIds) {
val path = idToFile[fileId]?.path
if (path != null) {
paths.add(path)
filtered.add(fileId)
}
return fileIds.mapNotNull {
// null means it's outdated
idToFile[it]?.path
}
if (size > MINIMUM_GARBAGE_COLLECTIBLE_SIZE && filtered.size.toDouble() / fileIds.size.toDouble() < DELETED_TO_SIZE_TRESHOLD) {
lookupMap[key] = filtered
}
return paths
}
@Synchronized
@@ -81,8 +92,8 @@ open class LookupStorage(
val key = LookupSymbolKey(lookupSymbol.name, lookupSymbol.scope)
val paths = lookups[lookupSymbol]
val fileIds = paths.mapTo(TreeSet()) { pathToId[it]!! }
fileIds.addAll(lookupMap[key] ?: emptySet())
lookupMap[key] = fileIds
lookupMap.append(key, fileIds)
}
}
@@ -92,7 +103,6 @@ open class LookupStorage(
val id = fileToId[file] ?: continue
idToFile.remove(id)
fileToId.remove(file)
deletedCount++
}
}
@@ -103,7 +113,6 @@ open class LookupStorage(
}
size = 0
deletedCount = 0
super.clean()
}
@@ -111,18 +120,15 @@ open class LookupStorage(
@Synchronized
override fun flush(memoryCachesOnly: Boolean) {
try {
removeGarbageIfNeeded()
if (size > 0) {
if (!countersFile.exists()) {
countersFile.parentFile.mkdirs()
countersFile.createNewFile()
}
countersFile.writeText("$size\n$deletedCount")
countersFile.writeText("$size\n")
}
}
finally {
} finally {
super.flush(memoryCachesOnly)
}
}
@@ -137,13 +143,7 @@ open class LookupStorage(
return id
}
private fun removeGarbageIfNeeded(force: Boolean = false) {
if (force || (size > MINIMUM_GARBAGE_COLLECTIBLE_SIZE && deletedCount.toDouble() / size > DELETED_TO_SIZE_TRESHOLD)) {
doRemoveGarbage()
}
}
private fun doRemoveGarbage() {
private fun removeGarbageForTests() {
for (hash in lookupMap.keys) {
lookupMap[hash] = lookupMap[hash]!!.filter { it in idToFile }.toSet()
}
@@ -153,7 +153,6 @@ open class LookupStorage(
idToFile.clean()
fileToId.clean()
size = 0
deletedCount = 0
for ((file, oldId) in oldFileToId.entries.sortedBy { it.key.path }) {
val newId = addFileIfNeeded(file)
@@ -165,15 +164,16 @@ open class LookupStorage(
if (fileIds.isEmpty()) {
lookupMap.remove(lookup)
}
else {
} else {
lookupMap[lookup] = fileIds
}
}
}
@TestOnly fun forceGC() {
removeGarbageIfNeeded(force = true)
@TestOnly
fun forceGC() {
removeGarbageForTests()
flush(false)
}

View File

@@ -1104,6 +1104,11 @@ open class ProtoCompareGenerated(
if (!checkEquals(old.setter, new.setter)) return false
}
if (old.hasDelegateMethod() != new.hasDelegateMethod()) return false
if (old.hasDelegateMethod()) {
if (!checkEquals(old.delegateMethod, new.delegateMethod)) return false
}
return true
}
@@ -2353,6 +2358,10 @@ fun JvmProtoBuf.JvmPropertySignature.hashCode(stringIndexes: (Int) -> Int, fqNam
hashCode = 31 * hashCode + setter.hashCode(stringIndexes, fqNameIndexes, typeById)
}
if (hasDelegateMethod()) {
hashCode = 31 * hashCode + delegateMethod.hashCode(stringIndexes, fqNameIndexes, typeById)
}
return hashCode
}

View File

@@ -255,22 +255,23 @@ fun withSubtypes(
typeFqName: FqName,
caches: Iterable<IncrementalCacheCommon>
): Set<FqName> {
val types = LinkedHashSet(listOf(typeFqName))
val subtypes = hashSetOf<FqName>()
val typesToProccess = LinkedHashSet(listOf(typeFqName))
val proccessedTypes = hashSetOf<FqName>()
while (types.isNotEmpty()) {
val iterator = types.iterator()
while (typesToProccess.isNotEmpty()) {
val iterator = typesToProccess.iterator()
val unprocessedType = iterator.next()
iterator.remove()
caches.asSequence()
.flatMap { it.getSubtypesOf(unprocessedType) }
.filter { it !in subtypes }
.forEach { types.add(it) }
.filter { it !in proccessedTypes }
.forEach { typesToProccess.add(it) }
subtypes.add(unprocessedType)
proccessedTypes.add(unprocessedType)
}
return subtypes
return proccessedTypes
}

View File

@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.incremental.storage
import java.io.File
internal class LookupMap(storage: File) : BasicMap<LookupSymbolKey, Collection<Int>>(storage, LookupSymbolKeyDescriptor, IntCollectionExternalizer) {
class LookupMap(storage: File) : BasicMap<LookupSymbolKey, Collection<Int>>(storage, LookupSymbolKeyDescriptor, IntCollectionExternalizer) {
override fun dumpKey(key: LookupSymbolKey): String = key.toString()
override fun dumpValue(value: Collection<Int>): String = value.toString()
@@ -27,6 +27,10 @@ internal class LookupMap(storage: File) : BasicMap<LookupSymbolKey, Collection<I
storage.append(LookupSymbolKey(name, scope), listOf(fileId))
}
fun append(lookup: LookupSymbolKey, fileIds: Collection<Int>) {
storage.append(lookup, fileIds)
}
operator fun get(key: LookupSymbolKey): Collection<Int>? = storage[key]
operator fun set(key: LookupSymbolKey, fileIds: Set<Int>) {

View File

@@ -21,23 +21,49 @@ import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.EnumeratorStringDescriptor
import com.intellij.util.io.IOUtil
import com.intellij.util.io.KeyDescriptor
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.cli.common.toBooleanLenient
import java.io.DataInput
import java.io.DataInputStream
import java.io.DataOutput
import java.io.File
import java.util.*
/**
* Storage versioning:
* 0 - only name and value hashes are saved
* 1 - name and scope are saved
*/
object LookupSymbolKeyDescriptor : KeyDescriptor<LookupSymbolKey> {
override fun read(input: DataInput): LookupSymbolKey {
val first = input.readInt()
val second = input.readInt()
return LookupSymbolKey(first, second)
val version = input.readByte()
return when (version.toInt()) {
0 -> {
val name = input.readUTF()
val scope = input.readUTF()
LookupSymbolKey(name.hashCode(), scope.hashCode(), name, scope)
}
1 -> {
val first = input.readInt()
val second = input.readInt()
LookupSymbolKey(first, second, "", "")
}
else -> throw RuntimeException("Unknown version of LookupSymbolKeyDescriptor=${version}")
}
}
private val storeFullFqName = CompilerSystemProperties.COMPILE_INCREMENTAL_WITH_CLASSPATH_SHAPSHOTS.value.toBooleanLenient() ?: false
override fun save(output: DataOutput, value: LookupSymbolKey) {
output.writeInt(value.nameHash)
output.writeInt(value.scopeHash)
if (storeFullFqName) {
output.writeByte(0)
output.writeUTF(value.name)
output.writeUTF(value.scope)
} else {
output.writeByte(1)
output.writeInt(value.nameHash)
output.writeInt(value.scopeHash)
}
}
override fun getHashCode(value: LookupSymbolKey): Int = value.hashCode()

View File

@@ -16,8 +16,8 @@
package org.jetbrains.kotlin.incremental.storage
data class LookupSymbolKey(val nameHash: Int, val scopeHash: Int) : Comparable<LookupSymbolKey> {
constructor(name: String, scope: String) : this(name.hashCode(), scope.hashCode())
data class LookupSymbolKey(val nameHash: Int, val scopeHash: Int, val name:String, val scope:String) : Comparable<LookupSymbolKey> {
constructor(name: String, scope: String) : this(name.hashCode(), scope.hashCode(), name, scope)
override fun compareTo(other: LookupSymbolKey): Int {
val nameCmp = nameHash.compareTo(other.nameHash)
@@ -26,6 +26,26 @@ data class LookupSymbolKey(val nameHash: Int, val scopeHash: Int) : Comparable<L
return scopeHash.compareTo(other.scopeHash)
}
override fun hashCode(): Int {
var result = nameHash
result = 31 * result + scopeHash
return result
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as LookupSymbolKey
if (nameHash != other.nameHash) return false
if (scopeHash != other.scopeHash) return false
return true
}
}
data class ProtoMapValue(val isPackageFacade: Boolean, val bytes: ByteArray, val strings: Array<String>)

View File

@@ -3443,6 +3443,34 @@ public final class DebugJvmProtoBuf {
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature setter = 4;</code>
*/
org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignatureOrBuilder getSetterOrBuilder();
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
boolean hasDelegateMethod();
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature getDelegateMethod();
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignatureOrBuilder getDelegateMethodOrBuilder();
}
/**
* Protobuf type {@code org.jetbrains.kotlin.metadata.jvm.JvmPropertySignature}
@@ -3548,6 +3576,19 @@ public final class DebugJvmProtoBuf {
bitField0_ |= 0x00000008;
break;
}
case 42: {
org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.Builder subBuilder = null;
if (((bitField0_ & 0x00000010) == 0x00000010)) {
subBuilder = delegateMethod_.toBuilder();
}
delegateMethod_ = input.readMessage(org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.PARSER, extensionRegistry);
if (subBuilder != null) {
subBuilder.mergeFrom(delegateMethod_);
delegateMethod_ = subBuilder.buildPartial();
}
bitField0_ |= 0x00000010;
break;
}
}
}
} catch (org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException e) {
@@ -3684,11 +3725,48 @@ public final class DebugJvmProtoBuf {
return setter_;
}
public static final int DELEGATE_METHOD_FIELD_NUMBER = 5;
private org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature delegateMethod_;
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
public boolean hasDelegateMethod() {
return ((bitField0_ & 0x00000010) == 0x00000010);
}
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
public org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature getDelegateMethod() {
return delegateMethod_;
}
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
public org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignatureOrBuilder getDelegateMethodOrBuilder() {
return delegateMethod_;
}
private void initFields() {
field_ = org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmFieldSignature.getDefaultInstance();
syntheticMethod_ = org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.getDefaultInstance();
getter_ = org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.getDefaultInstance();
setter_ = org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.getDefaultInstance();
delegateMethod_ = org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.getDefaultInstance();
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -3715,6 +3793,9 @@ public final class DebugJvmProtoBuf {
if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeMessage(4, setter_);
}
if (((bitField0_ & 0x00000010) == 0x00000010)) {
output.writeMessage(5, delegateMethod_);
}
getUnknownFields().writeTo(output);
}
@@ -3740,6 +3821,10 @@ public final class DebugJvmProtoBuf {
size += org.jetbrains.kotlin.protobuf.CodedOutputStream
.computeMessageSize(4, setter_);
}
if (((bitField0_ & 0x00000010) == 0x00000010)) {
size += org.jetbrains.kotlin.protobuf.CodedOutputStream
.computeMessageSize(5, delegateMethod_);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -3853,6 +3938,7 @@ public final class DebugJvmProtoBuf {
getSyntheticMethodFieldBuilder();
getGetterFieldBuilder();
getSetterFieldBuilder();
getDelegateMethodFieldBuilder();
}
}
private static Builder create() {
@@ -3885,6 +3971,12 @@ public final class DebugJvmProtoBuf {
setterBuilder_.clear();
}
bitField0_ = (bitField0_ & ~0x00000008);
if (delegateMethodBuilder_ == null) {
delegateMethod_ = org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.getDefaultInstance();
} else {
delegateMethodBuilder_.clear();
}
bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
@@ -3945,6 +4037,14 @@ public final class DebugJvmProtoBuf {
} else {
result.setter_ = setterBuilder_.build();
}
if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
to_bitField0_ |= 0x00000010;
}
if (delegateMethodBuilder_ == null) {
result.delegateMethod_ = delegateMethod_;
} else {
result.delegateMethod_ = delegateMethodBuilder_.build();
}
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -3973,6 +4073,9 @@ public final class DebugJvmProtoBuf {
if (other.hasSetter()) {
mergeSetter(other.getSetter());
}
if (other.hasDelegateMethod()) {
mergeDelegateMethod(other.getDelegateMethod());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -4500,6 +4603,167 @@ public final class DebugJvmProtoBuf {
return setterBuilder_;
}
private org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature delegateMethod_ = org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.getDefaultInstance();
private org.jetbrains.kotlin.protobuf.SingleFieldBuilder<
org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature, org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.Builder, org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignatureOrBuilder> delegateMethodBuilder_;
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
public boolean hasDelegateMethod() {
return ((bitField0_ & 0x00000010) == 0x00000010);
}
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
public org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature getDelegateMethod() {
if (delegateMethodBuilder_ == null) {
return delegateMethod_;
} else {
return delegateMethodBuilder_.getMessage();
}
}
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
public Builder setDelegateMethod(org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature value) {
if (delegateMethodBuilder_ == null) {
if (value == null) {
throw new NullPointerException();
}
delegateMethod_ = value;
onChanged();
} else {
delegateMethodBuilder_.setMessage(value);
}
bitField0_ |= 0x00000010;
return this;
}
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
public Builder setDelegateMethod(
org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.Builder builderForValue) {
if (delegateMethodBuilder_ == null) {
delegateMethod_ = builderForValue.build();
onChanged();
} else {
delegateMethodBuilder_.setMessage(builderForValue.build());
}
bitField0_ |= 0x00000010;
return this;
}
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
public Builder mergeDelegateMethod(org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature value) {
if (delegateMethodBuilder_ == null) {
if (((bitField0_ & 0x00000010) == 0x00000010) &&
delegateMethod_ != org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.getDefaultInstance()) {
delegateMethod_ =
org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.newBuilder(delegateMethod_).mergeFrom(value).buildPartial();
} else {
delegateMethod_ = value;
}
onChanged();
} else {
delegateMethodBuilder_.mergeFrom(value);
}
bitField0_ |= 0x00000010;
return this;
}
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
public Builder clearDelegateMethod() {
if (delegateMethodBuilder_ == null) {
delegateMethod_ = org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.getDefaultInstance();
onChanged();
} else {
delegateMethodBuilder_.clear();
}
bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
public org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.Builder getDelegateMethodBuilder() {
bitField0_ |= 0x00000010;
onChanged();
return getDelegateMethodFieldBuilder().getBuilder();
}
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
public org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignatureOrBuilder getDelegateMethodOrBuilder() {
if (delegateMethodBuilder_ != null) {
return delegateMethodBuilder_.getMessageOrBuilder();
} else {
return delegateMethod_;
}
}
/**
* <code>optional .org.jetbrains.kotlin.metadata.jvm.JvmMethodSignature delegate_method = 5;</code>
*
* <pre>
* The delegate field of delegated properties may be optimized out; `getDelegate` should
* then call this method instead
* </pre>
*/
private org.jetbrains.kotlin.protobuf.SingleFieldBuilder<
org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature, org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.Builder, org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignatureOrBuilder>
getDelegateMethodFieldBuilder() {
if (delegateMethodBuilder_ == null) {
delegateMethodBuilder_ = new org.jetbrains.kotlin.protobuf.SingleFieldBuilder<
org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature, org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignature.Builder, org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf.JvmMethodSignatureOrBuilder>(
getDelegateMethod(),
getParentForChildren(),
isClean());
delegateMethod_ = null;
}
return delegateMethodBuilder_;
}
// @@protoc_insertion_point(builder_scope:org.jetbrains.kotlin.metadata.jvm.JvmPropertySignature)
}
@@ -4740,7 +5004,7 @@ public final class DebugJvmProtoBuf {
"\020DESC_TO_CLASS_ID\020\002\"<\n\022JvmMethodSignatur" +
"e\022\022\n\004name\030\001 \001(\005B\004\230\265\030\001\022\022\n\004desc\030\002 \001(\005B\004\230\265\030" +
"\001\";\n\021JvmFieldSignature\022\022\n\004name\030\001 \001(\005B\004\230\265" +
"\030\001\022\022\n\004desc\030\002 \001(\005B\004\230\265\030\001\"\272\002\n\024JvmPropertySi" +
"\030\001\022\022\n\004desc\030\002 \001(\005B\004\230\265\030\001\"\212\003\n\024JvmPropertySi" +
"gnature\022C\n\005field\030\001 \001(\01324.org.jetbrains.k" +
"otlin.metadata.jvm.JvmFieldSignature\022O\n\020",
"synthetic_method\030\002 \001(\01325.org.jetbrains.k" +
@@ -4748,11 +5012,13 @@ public final class DebugJvmProtoBuf {
"\006getter\030\003 \001(\01325.org.jetbrains.kotlin.met" +
"adata.jvm.JvmMethodSignature\022E\n\006setter\030\004" +
" \001(\01325.org.jetbrains.kotlin.metadata.jvm" +
".JvmMethodSignature\022N\n\017delegate_method\030\005" +
" \001(\01325.org.jetbrains.kotlin.metadata.jvm" +
".JvmMethodSignature:\200\001\n\025constructor_sign" +
"ature\022*.org.jetbrains.kotlin.metadata.Co" +
"nstructor\030d \001(\01325.org.jetbrains.kotlin.m" +
"nstructor\030d \001(\01325.org.jetbrains.kotlin.m",
"etadata.jvm.JvmMethodSignature:x\n\020method" +
"_signature\022\'.org.jetbrains.kotlin.metada",
"_signature\022\'.org.jetbrains.kotlin.metada" +
"ta.Function\030d \001(\01325.org.jetbrains.kotlin" +
".metadata.jvm.JvmMethodSignature:O\n\030lamb" +
"da_class_origin_name\022\'.org.jetbrains.kot" +
@@ -4760,9 +5026,9 @@ public final class DebugJvmProtoBuf {
"perty_signature\022\'.org.jetbrains.kotlin.m" +
"etadata.Property\030d \001(\01327.org.jetbrains.k" +
"otlin.metadata.jvm.JvmPropertySignature:" +
"9\n\005flags\022\'.org.jetbrains.kotlin.metadata" +
"9\n\005flags\022\'.org.jetbrains.kotlin.metadata",
".Property\030e \001(\005:\0010:g\n\017type_annotation\022#." +
"org.jetbrains.kotlin.metadata.Type\030d \003(\013",
"org.jetbrains.kotlin.metadata.Type\030d \003(\013" +
"2).org.jetbrains.kotlin.metadata.Annotat" +
"ion:3\n\006is_raw\022#.org.jetbrains.kotlin.met" +
"adata.Type\030e \001(\010:z\n\031type_parameter_annot" +
@@ -4770,9 +5036,9 @@ public final class DebugJvmProtoBuf {
"peParameter\030d \003(\0132).org.jetbrains.kotlin" +
".metadata.Annotation:E\n\021class_module_nam" +
"e\022$.org.jetbrains.kotlin.metadata.Class\030" +
"e \001(\005B\004\230\265\030\001:k\n\024class_local_variable\022$.or" +
"e \001(\005B\004\230\265\030\001:k\n\024class_local_variable\022$.or",
"g.jetbrains.kotlin.metadata.Class\030f \003(\0132" +
"\'.org.jetbrains.kotlin.metadata.Property",
"\'.org.jetbrains.kotlin.metadata.Property" +
":P\n\034anonymous_object_origin_name\022$.org.j" +
"etbrains.kotlin.metadata.Class\030g \001(\005B\004\230\265" +
"\030\001:@\n\017jvm_class_flags\022$.org.jetbrains.ko" +
@@ -4780,7 +5046,7 @@ public final class DebugJvmProtoBuf {
"module_name\022&.org.jetbrains.kotlin.metad" +
"ata.Package\030e \001(\005B\004\230\265\030\001:o\n\026package_local" +
"_variable\022&.org.jetbrains.kotlin.metadat" +
"a.Package\030f \003(\0132\'.org.jetbrains.kotlin.m" +
"a.Package\030f \003(\0132\'.org.jetbrains.kotlin.m",
"etadata.PropertyB\022B\020DebugJvmProtoBuf"
};
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
@@ -4826,7 +5092,7 @@ public final class DebugJvmProtoBuf {
internal_static_org_jetbrains_kotlin_metadata_jvm_JvmPropertySignature_fieldAccessorTable = new
org.jetbrains.kotlin.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_org_jetbrains_kotlin_metadata_jvm_JvmPropertySignature_descriptor,
new java.lang.String[] { "Field", "SyntheticMethod", "Getter", "Setter", });
new java.lang.String[] { "Field", "SyntheticMethod", "Getter", "Setter", "DelegateMethod", });
constructorSignature.internalInit(descriptor.getExtensions().get(0));
methodSignature.internalInit(descriptor.getExtensions().get(1));
lambdaClassOriginName.internalInit(descriptor.getExtensions().get(2));

View File

@@ -1,7 +1,6 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.crypto.checksum.Checksum
import org.gradle.plugins.ide.idea.model.IdeaModel
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import proguard.gradle.ProGuardTask
buildscript {
@@ -30,7 +29,7 @@ buildscript {
dependencies {
bootstrapCompilerClasspath(kotlin("compiler-embeddable", bootstrapKotlinVersion))
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.30")
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.31")
classpath(kotlin("gradle-plugin", bootstrapKotlinVersion))
classpath(kotlin("serialization", bootstrapKotlinVersion))
classpath("org.jetbrains.dokka:dokka-gradle-plugin:0.9.17")
@@ -56,13 +55,6 @@ pill {
val isTeamcityBuild = project.kotlinBuildProperties.isTeamcityBuild
val configuredJdks: List<JdkId> =
getConfiguredJdks().also {
it.forEach { jdkId ->
logger.info("Using ${jdkId.majorVersion} home: ${jdkId.homeDir}")
}
}
val defaultSnapshotVersion: String by extra
val buildNumber by extra(findProperty("build.number")?.toString() ?: defaultSnapshotVersion)
val kotlinVersion by extra(
@@ -114,37 +106,6 @@ subprojects {
extra["kotlinNativeVersion"] = kotlinNativeVersionObject
}
// Work-around necessary to avoid setting null javaHome. Will be removed after support of lazy task configuration
val jdkNotFoundConst = "JDK NOT FOUND"
if (isTeamcityBuild) {
extra["JDK_16"] = jdkPath("1.6")
extra["JDK_17"] = jdkPath("1.7")
} else {
extra["JDK_16"] = jdkPath("1.6", "1.8")
extra["JDK_17"] = jdkPath("1.7", "1.8")
}
extra["JDK_18"] = jdkPath("1.8")
extra["JDK_9"] = jdkPath("9")
extra["JDK_10"] = jdkPath("10")
extra["JDK_11"] = jdkPath("11")
extra["JDK_15"] = jdkPath("15")
// allow opening the project without setting up all env variables (see KT-26413)
if (!kotlinBuildProperties.isInIdeaSync) {
checkJDK()
}
fun checkJDK() {
val missingEnvVars = JdkMajorVersion.values()
.filter { it.isMandatory() && extra[it.name] == jdkNotFoundConst }
.mapTo(ArrayList()) { it.name }
if (missingEnvVars.isNotEmpty()) {
throw GradleException("Required environment variables are missing: ${missingEnvVars.joinToString()}")
}
}
rootProject.apply {
from(rootProject.file("gradle/versions.gradle.kts"))
from(rootProject.file("gradle/report.gradle.kts"))
@@ -167,8 +128,9 @@ extra["versions.junit"] = "4.12"
extra["versions.javaslang"] = "2.0.6"
extra["versions.ant"] = "1.10.7"
extra["versions.android"] = "2.3.1"
extra["versions.kotlinx-coroutines-core"] = "1.3.8"
extra["versions.kotlinx-coroutines-jdk8"] = "1.3.8"
extra["versions.kotlinx-coroutines-core"] = "1.5.0"
extra["versions.kotlinx-coroutines-core-jvm"] = "1.5.0"
extra["versions.kotlinx-coroutines-jdk8"] = "1.5.0"
extra["versions.json"] = "20160807"
extra["versions.native-platform"] = "0.14"
extra["versions.robolectric"] = "4.0"
@@ -186,12 +148,11 @@ 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.5.30-dev-1916"
extra["versions.kotlin-native"] = "1.6.0-dev-248"
}
val effectSystemEnabled by extra(project.getBooleanProperty("kotlin.compiler.effectSystemEnabled") ?: false)
val newInferenceEnabled by extra(project.getBooleanProperty("kotlin.compiler.newInferenceEnabled") ?: false)
val useJvmIrBackend by extra(project.kotlinBuildProperties.useIR)
val useJvmFir by extra(project.kotlinBuildProperties.useFir)
val intellijSeparateSdks = project.getBooleanProperty("intellijSeparateSdks") ?: false
@@ -200,7 +161,11 @@ extra["intellijSeparateSdks"] = intellijSeparateSdks
extra["IntellijCoreDependencies"] =
listOf(
"asm-all-8.0.1",
when {
Platform[203].orHigher() -> "asm-all-9.0"
Platform[202].orHigher() -> "asm-all-8.0.1"
else -> "asm-all-7.0.1"
},
"guava",
"jdom",
"jna",
@@ -252,6 +217,7 @@ extra["compilerModules"] = arrayOf(
":compiler:incremental-compilation-impl",
":compiler:compiler.version",
":js:js.ast",
":js:js.sourcemap",
":js:js.serializer",
":js:js.parser",
":js:js.config",
@@ -333,6 +299,11 @@ extra["compilerArtifactsForIde"] = listOf(
":prepare:ide-plugin-dependencies:lombok-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:kotlin-compiler-tests-for-ide",
":prepare:ide-plugin-dependencies:kotlin-compiler-testdata-for-ide",
":prepare:ide-plugin-dependencies:kotlin-stdlib-minimal-for-test-for-ide",
":prepare:ide-plugin-dependencies:low-level-api-fir-for-ide",
":prepare:ide-plugin-dependencies:high-level-api-for-ide",
":prepare:ide-plugin-dependencies:high-level-api-fir-for-ide",
":prepare:ide-plugin-dependencies:high-level-api-fir-tests-for-ide",
":kotlin-script-runtime",
":kotlin-script-util",
":kotlin-scripting-common",
@@ -383,7 +354,12 @@ val coreLibProjects = listOfNotNull(
val projectsWithDisabledFirBootstrap = coreLibProjects + listOf(
":kotlin-gradle-plugin",
":kotlinx-metadata",
":kotlinx-metadata-jvm"
":kotlinx-metadata-jvm",
// For some reason stdlib isn't imported correctly for this module
// Probably it's related to kotlin-test module usage
":kotlin-gradle-statistics",
// Requires serialization plugin
":wasm:wasm.ir"
)
val gradlePluginProjects = listOf(
@@ -417,8 +393,6 @@ fun Task.listConfigurationContents(configName: String) {
}
}
val defaultJvmTarget = "1.8"
val defaultJavaHome = jdkPath(if (Platform[203].orHigher()) "11" else defaultJvmTarget)
val ignoreTestFailures by extra(project.kotlinBuildProperties.ignoreTestFailures)
allprojects {
@@ -464,17 +438,16 @@ allprojects {
}
}
jvmTarget = defaultJvmTarget
javaHome = defaultJavaHome
// There are problems with common build dir:
// - some tests (in particular js and binary-compatibility-validator depend on the fixed (default) location
// - idea seems unable to exclude common buildDir from indexing
// therefore it is disabled by default
// buildDir = File(commonBuildDir, project.name)
configureJvmProject(javaHome!!, jvmTarget!!)
project.configureJvmDefaultToolchain()
plugins.withId("java-base") {
project.configureShadowJarSubstitutionInCompileClasspath()
}
val commonCompilerArgs = listOfNotNull(
"-Xopt-in=kotlin.RequiresOptIn",
@@ -501,11 +474,7 @@ allprojects {
kotlinOptions {
freeCompilerArgs = commonCompilerArgs + jvmCompilerArgs
if (useJvmIrBackend) {
useIR = true
}
if (useJvmFir && this@allprojects.name !in projectsWithDisabledFirBootstrap) {
if (useJvmFir && this@allprojects.path !in projectsWithDisabledFirBootstrap) {
freeCompilerArgs += "-Xuse-fir"
freeCompilerArgs += "-Xabi-stability=stable"
}
@@ -572,12 +541,9 @@ allprojects {
register("checkBuild")
}
afterEvaluate {
if (javaHome != defaultJavaHome || jvmTarget != defaultJvmTarget) {
logger.info("configuring project $name to compile to the target jvm version $jvmTarget using jdk: $javaHome")
configureJvmProject(javaHome!!, jvmTarget!!)
} // else we will actually fail during the first task execution. We could not fail before configuration is done due to impact on import in IDE
apply(from = "$rootDir/gradle/cacheRedirector.gradle.kts")
afterEvaluate {
fun File.toProjectRootRelativePathOrSelf() = (relativeToOrNull(rootDir)?.takeUnless { it.startsWith("..") } ?: this).path
fun FileCollection.printClassPath(role: String) =
@@ -606,7 +572,6 @@ allprojects {
?.exclude("org.jetbrains.kotlin", "kotlin-scripting-compiler-embeddable")
}
apply(from = "$rootDir/gradle/cacheRedirector.gradle.kts")
apply(from = "$rootDir/gradle/testRetry.gradle.kts")
}
}
@@ -769,8 +734,6 @@ tasks {
dependsOn(":kotlin-scripting-jsr223-test:embeddableTest")
dependsOn(":kotlin-main-kts-test:test")
dependsOn(":kotlin-main-kts-test:testWithIr")
dependsOn(":kotlin-scripting-ide-services-test:test")
dependsOn(":kotlin-scripting-ide-services-test:embeddableTest")
dependsOn(":kotlin-scripting-js-test:test")
}
@@ -814,6 +777,7 @@ tasks {
register("distTest") {
dependsOn("compilerTest")
dependsOn("frontendApiTests")
dependsOn("toolsTest")
dependsOn("gradlePluginTest")
dependsOn("examplesTest")
@@ -875,14 +839,23 @@ tasks {
dependsOn("dist")
dependsOn(
":idea:idea-fir:test",
":idea:idea-frontend-api:test",
":idea:idea-frontend-fir:test",
":idea:idea-frontend-fir:idea-fir-low-level-api:test",
":idea:idea-frontend-fir:fir-low-level-api-ide-impl:test",
":plugins:uast-kotlin-fir:test",
":idea:idea-fir-fe10-binding:test"
)
}
register("frontendApiTests") {
dependsOn("dist")
dependsOn(
":idea-frontend-api:test",
":idea-frontend-fir:test",
":idea-frontend-fir:idea-fir-low-level-api:test"
)
}
register("android-ide-tests") {
dependsOn("dist")
dependsOn(
@@ -1082,66 +1055,6 @@ configure<IdeaModel> {
}
}
fun jdkPathOrNull(version: String): String? {
val jdkName = "JDK_${version.replace(".", "")}"
val jdkMajorVersion = JdkMajorVersion.valueOf(jdkName)
return configuredJdks.find { it.majorVersion == jdkMajorVersion }?.homeDir?.canonicalPath
}
fun jdkPath(version: String, vararg replacementVersions: String): String {
return jdkPathOrNull(version) ?: run {
replacementVersions.asSequence().map { jdkPathOrNull(it) }.find { it != null }
} ?: jdkNotFoundConst
}
fun Project.configureJvmProject(javaHome: String, javaVersion: String) {
val currentJavaHome = File(System.getProperty("java.home")!!).canonicalPath
val shouldFork = !currentJavaHome.startsWith(File(javaHome).canonicalPath)
tasks.withType<JavaCompile> {
if (name != "compileJava9Java") {
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
options.isFork = shouldFork
options.forkOptions.javaHome = file(javaHome)
options.compilerArgs.add("-proc:none")
options.encoding = "UTF-8"
}
}
tasks.withType<KotlinCompile> {
kotlinOptions.jdkHome = javaHome.takeUnless { kotlinBuildProperties.suppressJdkHomeWarning }
kotlinOptions.jvmTarget = javaVersion
kotlinOptions.freeCompilerArgs += "-Xjvm-default=compatibility"
}
tasks.withType<Test> {
executable = File(javaHome, "bin/java").canonicalPath
}
plugins.withId("java-base") {
configureShadowJarSubstitutionInCompileClasspath()
}
}
fun Project.configureShadowJarSubstitutionInCompileClasspath() {
val substitutionMap = mapOf(":kotlin-reflect" to ":kotlin-reflect-api")
fun configureSubstitution(substitution: DependencySubstitution) {
val requestedProject = (substitution.requested as? ProjectComponentSelector)?.projectPath ?: return
val replacementProject = substitutionMap[requestedProject] ?: return
substitution.useTarget(project(replacementProject), "Non-default shadow jars should not be used in compile classpath")
}
sourceSets.all {
for (configName in listOf(compileOnlyConfigurationName, compileClasspathConfigurationName)) {
configurations.getByName(configName).resolutionStrategy.dependencySubstitution {
all(::configureSubstitution)
}
}
}
}
tasks.register("findShadowJarsInClasspath") {
doLast {
fun Collection<File>.printSorted(indent: String = " ") {
@@ -1209,3 +1122,19 @@ if (disableVerificationTasks) {
}
}
}
plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin::class) {
extensions.configure(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension::class.java) {
nodeVersion = "16.2.0"
}
}
afterEvaluate {
val cacheRedirectorEnabled = findProperty("cacheRedirectorEnabled")?.toString()?.toBoolean() == true
if (cacheRedirectorEnabled) {
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin::class.java) {
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().downloadBaseUrl =
"https://cache-redirector.jetbrains.com/github.com/yarnpkg/yarn/releases/download"
}
}
}

View File

@@ -22,7 +22,7 @@ buildscript {
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.30")
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.31")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:${project.bootstrapKotlinVersion}")
}
@@ -143,7 +143,7 @@ java {
dependencies {
implementation(kotlin("stdlib", embeddedKotlinVersion))
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.30")
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.31")
implementation("com.gradle.publish:plugin-publish-plugin:0.14.0")
implementation("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")
@@ -155,10 +155,10 @@ dependencies {
implementation("net.sf.proguard:proguard-gradle:6.2.2")
implementation("org.jetbrains.intellij.deps:asm-all:8.0.1")
implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:0.5")
implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:1.0.1")
implementation("org.gradle:test-retry-gradle-plugin:1.2.0")
implementation("com.gradle.enterprise:test-distribution-gradle-plugin:1.2.1")
implementation("com.gradle.enterprise:test-distribution-gradle-plugin:2.1")
compileOnly(gradleApi())

View File

@@ -21,4 +21,5 @@ val KotlinBuildProperties.ignoreTestFailures: Boolean get() = getBoolean("ignore
val KotlinBuildProperties.disableWerror: Boolean get() = getBoolean("kotlin.build.disable.werror", false)
val KotlinBuildProperties.suppressJdkHomeWarning: Boolean get() = getBoolean("kotlin.suppress.jdkHome.warning", false)
val KotlinBuildProperties.isObsoleteJdkOverrideEnabled: Boolean
get() = getBoolean("kotlin.build.isObsoleteJdkOverrideEnabled", false)

View File

@@ -4,32 +4,36 @@
*/
import groovy.lang.Closure
import org.gradle.api.JavaVersion
import org.gradle.api.file.FileCollection
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.*
import org.gradle.internal.jvm.Jvm
import org.gradle.internal.jvm.inspection.JvmVersionDetector
import org.gradle.jvm.toolchain.JavaLauncher
import org.gradle.kotlin.dsl.property
import proguard.ClassSpecification
import java.io.File
import javax.inject.Inject
@CacheableTask
open class CacheableProguardTask @Inject constructor(
private val jvmVersionDetector: JvmVersionDetector
) : proguard.gradle.ProGuardTask() {
open class CacheableProguardTask : proguard.gradle.ProGuardTask() {
@Internal
var jdkHome: File? = null
@get:Internal
val javaLauncher: Property<JavaLauncher> = project.objects.property()
@get:Internal
val jdkHomePath: Provider<File> = javaLauncher.map { it.metadata.installationPath.asFile }
@get:Optional
@get:Input
internal val jdkMajorVersion: String?
get() = jdkHome?.let { jvmVersionDetector.getJavaVersion(Jvm.forHome(jdkHome)) }?.majorVersion
internal val jdkMajorVersion: Provider<JavaVersion> = javaLauncher.map {
JavaVersion.toVersion(it.metadata.languageVersion.toString())
}
@CompileClasspath
override fun getLibraryJarFileCollection(): FileCollection = super.getLibraryJarFileCollection().filter { libraryFile ->
jdkHome?.let { !libraryFile.absoluteFile.startsWith(it.absoluteFile) } ?: true
}
override fun getLibraryJarFileCollection(): FileCollection = super.getLibraryJarFileCollection()
.filter { libraryFile ->
jdkHomePath.orNull?.let { !libraryFile.absoluteFile.startsWith(it.absoluteFile) } ?: true
}
@InputFiles
@PathSensitive(PathSensitivity.RELATIVE)

View File

@@ -86,4 +86,7 @@ val Project.isConfigurationCacheDisabled
get() = (gradle.startParameter as? org.gradle.api.internal.StartParameterInternal)?.isConfigurationCache != true
val Project.isIdeaActive
get() = providers.systemProperty("idea.active").forUseAtConfigurationTime().isPresent
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")

View File

@@ -0,0 +1,144 @@
/*
* 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.
*/
import com.github.jengelman.gradle.plugins.shadow.relocation.RelocateClassContext
import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
import org.gradle.api.file.FileTreeElement
import shadow.org.apache.tools.zip.ZipEntry
import shadow.org.apache.tools.zip.ZipOutputStream
import shadow.org.codehaus.plexus.util.IOUtil
import shadow.org.codehaus.plexus.util.ReaderFactory
import shadow.org.codehaus.plexus.util.WriterFactory
import shadow.org.codehaus.plexus.util.xml.Xpp3Dom
import shadow.org.codehaus.plexus.util.xml.Xpp3DomBuilder
import shadow.org.codehaus.plexus.util.xml.Xpp3DomWriter
import java.io.*
import java.lang.Exception
import java.util.LinkedHashMap
/**
* A resource processor that aggregates plexus `components.xml` files.
*
* Fixed version of [com.github.jengelman.gradle.plugins.shadow.transformers.ComponentsXmlResourceTransformer],
* may be dropped after [the fix in ShadowJAR](https://github.com/johnrengelman/shadow/pull/678/files) will be accepted
*/
class ComponentsXmlResourceTransformerPatched : Transformer {
private val components: MutableMap<String, Xpp3Dom> =
LinkedHashMap<String, Xpp3Dom>()
override fun canTransformResource(element: FileTreeElement): Boolean {
val path = element.relativePath.pathString
return COMPONENTS_XML_PATH == path
}
override fun transform(context: TransformerContext) {
val newDom: Xpp3Dom = try {
val bis: BufferedInputStream = object : BufferedInputStream(context.getIs()) {
override fun close() {
// leave ZIP open
}
}
val reader: Reader = ReaderFactory.newXmlReader(bis)
Xpp3DomBuilder.build(reader)
} catch (e: Exception) {
throw (IOException("Error parsing components.xml in " + context.getIs()).initCause(e) as IOException)
}
// Only try to merge in components if there are some elements in the component-set
if (newDom.getChild("components") == null) {
return
}
val children: Array<Xpp3Dom>? = newDom.getChild("components")?.getChildren("component")
children?.forEach { component ->
var role: String? = getValue(component, "role")
role = getRelocatedClass(role, context)
setValue(component, "role", role)
val roleHint = getValue(component, "role-hint")
var impl: String? = getValue(component, "implementation")
impl = getRelocatedClass(impl, context)
setValue(component, "implementation", impl)
val key = "$role:$roleHint"
if (components.containsKey(key)) {
// configuration carry over
val dom: Xpp3Dom? = components[key]
if (dom?.getChild("configuration") != null) {
component.addChild(dom.getChild("configuration"))
}
}
val requirements: Xpp3Dom? = component.getChild("requirements")
if (requirements != null && requirements.childCount > 0) {
for (r in requirements.childCount - 1 downTo 0) {
val requirement: Xpp3Dom = requirements.getChild(r)
var requiredRole: String? = getValue(requirement, "role")
requiredRole = getRelocatedClass(requiredRole, context)
setValue(requirement, "role", requiredRole)
}
}
components[key] = component
}
}
override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) {
val data = transformedResource
val entry = ZipEntry(COMPONENTS_XML_PATH)
entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time)
os.putNextEntry(entry)
IOUtil.copy(data, os)
components.clear()
}
override fun hasTransformedResource(): Boolean {
return components.isNotEmpty()
}
private val transformedResource: ByteArray
get() {
val baos = ByteArrayOutputStream(1024 * 4)
val writer: Writer = WriterFactory.newXmlWriter(baos)
try {
val dom = Xpp3Dom("component-set")
val componentDom = Xpp3Dom("components")
dom.addChild(componentDom)
for (component in components.values) {
componentDom.addChild(component)
}
Xpp3DomWriter.write(writer, dom)
} finally {
IOUtil.close(writer)
}
return baos.toByteArray()
}
companion object {
private const val COMPONENTS_XML_PATH = "META-INF/plexus/components.xml"
private fun getRelocatedClass(className: String?, context: TransformerContext): String? {
val relocators = context.relocators
val stats = context.stats
if (className != null && className.isNotEmpty() && relocators != null) {
for (relocator in relocators) {
if (relocator.canRelocateClass(className)) {
val relocateClassContext = RelocateClassContext(className, stats)
return relocator.relocateClass(relocateClassContext)
}
}
}
return className
}
private fun getValue(dom: Xpp3Dom, element: String): String {
val child: Xpp3Dom? = dom.getChild(element)
return if (child?.value != null) child.value else ""
}
private fun setValue(dom: Xpp3Dom, element: String, value: String?) {
val child: Xpp3Dom? = dom.getChild(element)
if (value == null || value.isEmpty()) {
return
}
child?.value = value
}
}
}

View File

@@ -0,0 +1,183 @@
@file:JvmName("JvmToolchain")
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.jvm.toolchain.*
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
enum class JdkMajorVersion(
val majorVersion: Int,
val targetName: String = majorVersion.toString(),
val overrideMajorVersion: Int? = null,
private val mandatory: Boolean = true
) {
JDK_1_6(6, targetName = "1.6", overrideMajorVersion = 8),
JDK_1_7(7, targetName = "1.7", overrideMajorVersion = 8),
JDK_1_8(8, targetName = "1.8"),
JDK_9(9, overrideMajorVersion = 11),
JDK_10(10, mandatory = false, overrideMajorVersion = 11),
JDK_11(11, mandatory = false),
JDK_15(15, mandatory = false),
JDK_16(16, mandatory = false);
fun isMandatory(): Boolean = mandatory
companion object {
fun fromMajorVersion(majorVersion: Int) = values().first { it.majorVersion == majorVersion }
}
}
fun Project.configureJvmDefaultToolchain() {
configureJvmToolchain(JdkMajorVersion.JDK_1_8)
}
fun Project.shouldOverrideObsoleteJdk(
jdkVersion: JdkMajorVersion
): Boolean = kotlinBuildProperties.isObsoleteJdkOverrideEnabled &&
jdkVersion.overrideMajorVersion != null
fun Project.configureJvmToolchain(
jdkVersion: JdkMajorVersion
) {
// Ensure java only modules also set default toolchain
configureJavaOnlyToolchain(jdkVersion)
plugins.withId("org.jetbrains.kotlin.jvm") {
val kotlinExtension = extensions.getByType<KotlinTopLevelExtension>()
if (shouldOverrideObsoleteJdk(jdkVersion)) {
kotlinExtension.jvmToolchain {
(this as JavaToolchainSpec).languageVersion
.set(JavaLanguageVersion.of(jdkVersion.overrideMajorVersion!!))
}
updateJvmTarget(jdkVersion.targetName)
} else {
kotlinExtension.jvmToolchain {
(this as JavaToolchainSpec).languageVersion
.set(JavaLanguageVersion.of(jdkVersion.majorVersion))
}
}
tasks
.matching { it.name != "compileJava9Java" && it is JavaCompile }
.configureEach {
with(this as JavaCompile) {
options.compilerArgs.add("-proc:none")
options.encoding = "UTF-8"
}
}
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions.freeCompilerArgs += "-Xjvm-default=compatibility"
}
}
}
fun Project.configureJavaOnlyToolchain(
jdkVersion: JdkMajorVersion
) {
plugins.withId("java-base") {
val javaExtension = extensions.getByType<JavaPluginExtension>()
if (shouldOverrideObsoleteJdk(jdkVersion)) {
javaExtension.toolchain {
languageVersion.set(
JavaLanguageVersion.of(jdkVersion.overrideMajorVersion!!)
)
}
tasks.withType<JavaCompile>().configureEach {
targetCompatibility = jdkVersion.targetName
sourceCompatibility = jdkVersion.targetName
}
} else {
javaExtension.toolchain {
languageVersion.set(
JavaLanguageVersion.of(jdkVersion.majorVersion)
)
}
}
}
}
fun KotlinCompile.configureTaskToolchain(
jdkVersion: JdkMajorVersion
) {
if (project.shouldOverrideObsoleteJdk(jdkVersion)) {
kotlinJavaToolchain.toolchain.use(
project.getToolchainLauncherFor(
JdkMajorVersion.fromMajorVersion(
jdkVersion.overrideMajorVersion!!
)
)
)
kotlinOptions {
jvmTarget = jdkVersion.targetName
}
} else {
kotlinJavaToolchain.toolchain.use(
project.getToolchainLauncherFor(jdkVersion)
)
}
}
fun JavaCompile.configureTaskToolchain(
jdkVersion: JdkMajorVersion
) {
if (project.shouldOverrideObsoleteJdk(jdkVersion)) {
javaCompiler.set(
project.getToolchainCompilerFor(
JdkMajorVersion.fromMajorVersion(
jdkVersion.overrideMajorVersion!!
)
)
)
targetCompatibility = jdkVersion.targetName
sourceCompatibility = jdkVersion.targetName
} else {
javaCompiler.set(project.getToolchainCompilerFor(jdkVersion))
}
}
fun Project.updateJvmTarget(
jvmTarget: String
) {
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions.jvmTarget = jvmTarget
}
tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = jvmTarget
targetCompatibility = jvmTarget
}
}
private fun Project.getToolchainCompilerFor(
jdkVersion: JdkMajorVersion
): Provider<JavaCompiler> {
val service = project.extensions.getByType<JavaToolchainService>()
return service.compilerFor {
this.languageVersion.set(JavaLanguageVersion.of(jdkVersion.majorVersion))
}
}
fun Project.getToolchainLauncherFor(
jdkVersion: JdkMajorVersion
): Provider<JavaLauncher> {
val service = project.extensions.getByType<JavaToolchainService>()
val jdkVersionWithOverride = project.getJdkVersionWithOverride(jdkVersion)
return service.launcherFor {
this.languageVersion.set(JavaLanguageVersion.of(jdkVersionWithOverride.majorVersion))
}
}
fun Project.getJdkVersionWithOverride(jdkVersion: JdkMajorVersion): JdkMajorVersion {
return if (project.shouldOverrideObsoleteJdk(jdkVersion)) {
JdkMajorVersion.fromMajorVersion(jdkVersion.overrideMajorVersion!!)
} else {
jdkVersion
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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:JvmName("LibrariesCommon")
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.withType
import org.gradle.process.CommandLineArgumentProvider
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@JvmOverloads
fun Project.configureJava9Compilation(
moduleName: String,
moduleOutputs: Collection<FileCollection> = setOf(sourceSets["main"].output)
) {
configurations["java9CompileClasspath"].extendsFrom(configurations["compileClasspath"])
tasks.named("compileJava9Java", JavaCompile::class.java) {
dependsOn(moduleOutputs)
targetCompatibility = JavaVersion.VERSION_1_9.toString()
sourceCompatibility = JavaVersion.VERSION_1_9.toString()
configureTaskToolchain(JdkMajorVersion.JDK_9)
// module-info.java should be in java9 source set by convention
val java9SourceSet = sourceSets["java9"].java
destinationDir = file("${java9SourceSet.outputDir}/META-INF/versions/9")
options.sourcepath = files(java9SourceSet.srcDirs)
val compileClasspath = configurations["java9CompileClasspath"]
val moduleFiles = objects.fileCollection().from(moduleOutputs)
val modulePath = compileClasspath.filter { it !in moduleFiles.files }
classpath = objects.fileCollection().from()
options.compilerArgumentProviders.add(
Java9AdditionalArgumentsProvider(
moduleName,
moduleFiles,
modulePath
)
)
}
}
private class Java9AdditionalArgumentsProvider(
private val moduleName: String,
private val moduleFiles: FileCollection,
private val modulePath: FileCollection
) : CommandLineArgumentProvider {
override fun asArguments(): Iterable<String> = listOf(
"--module-path", modulePath.asPath,
"--patch-module", "$moduleName=${moduleFiles.asPath}",
"-Xlint:-requires-transitive-automatic" // suppress automatic module transitive dependencies in kotlin.test
)
}
fun Project.disableDeprecatedJvmTargetWarning() {
if (!kotlinBuildProperties.useFir && !kotlinBuildProperties.disableWerror) {
val tasksWithWarnings: List<String> by rootProject.extra
tasks.withType<KotlinCompile>().configureEach {
if (!tasksWithWarnings.contains(path)) {
kotlinOptions {
allWarningsAsErrors = true
freeCompilerArgs += "-Xsuppress-deprecated-jvm-target-warning"
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
@file:Suppress("unused") // usages in build scripts are not tracked properly
import org.gradle.api.GradleException
import com.gradle.publish.PublishTask
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.artifacts.ConfigurablePublishArtifact
@@ -22,12 +22,12 @@ import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.tasks.GenerateModuleMetadata
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.Upload
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetContainer
import plugins.KotlinBuildPublishingPlugin
import plugins.mainPublicationName
private const val MAGIC_DO_NOT_CHANGE_TEST_JAR_TASK_NAME = "testJar"
@@ -62,8 +62,6 @@ fun Project.removeArtifacts(configuration: Configuration, task: Task) {
fun Project.noDefaultJar() {
tasks.named("jar").configure {
enabled = false
actions = emptyList()
configurations.forEach { cfg ->
removeArtifacts(cfg, this)
}
@@ -112,6 +110,8 @@ fun <T : Jar> Project.runtimeJar(task: TaskProvider<T>, body: T.() -> Unit = {})
addVariantsFromConfiguration(runtimeJar) { }
}
(components.findByName("java") as AdhocComponentWithVariants?)?.addVariantsFromConfiguration(runtimeJar) { }
return task
}
@@ -225,10 +225,23 @@ fun Project.publish(moduleMetadata: Boolean = false, configure: MavenPublication
val publication = extensions.findByType<PublishingExtension>()
?.publications
?.findByName(KotlinBuildPublishingPlugin.PUBLICATION_NAME) as MavenPublication
?.findByName(mainPublicationName) as MavenPublication
publication.configure()
}
fun Project.publishGradlePlugin() {
mainPublicationName = "pluginMaven"
publish()
afterEvaluate {
tasks.withType<PublishTask> {
// Makes plugin publication task reuse poms and metadata from publication named "pluginMaven"
useAutomatedPublishing()
useGradleModuleMetadataIfAvailable()
}
}
}
fun Project.idePluginDependency(block: () -> Unit) {
val shouldActivate = rootProject.findProperty("publish.ide.plugin.dependencies")?.toString()?.toBoolean() == true
if (shouldActivate) {

View File

@@ -9,15 +9,15 @@
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ExternalModuleDependency
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileCollection
import org.gradle.internal.jvm.Jvm
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.kotlin.dsl.accessors.runtime.addDependencyTo
import org.gradle.kotlin.dsl.closureOf
import org.gradle.kotlin.dsl.exclude
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.project
import java.io.File
@@ -124,6 +124,14 @@ fun DependencyHandler.add(configurationName: String, dependencyNotation: Any, co
}
}
fun Project.disableDependencyVerification() {
configurations.all {
resolutionStrategy {
disableDependencyVerification()
}
}
}
fun DependencyHandler.jpsLikeJarDependency(
dependencyNotation: Any,
scope: JpsDepScope,
@@ -281,14 +289,16 @@ fun Project.firstFromJavaHomeThatExists(vararg paths: String, jdkHome: File = Fi
fun Project.toolsJarApi(): Any =
if (kotlinBuildProperties.isInJpsBuildIdeaSync)
files(toolsJarFile() ?: error("tools.jar is not found!"))
toolsJar()
else
dependencies.project(":dependencies:tools-jar-api")
fun Project.toolsJar(): FileCollection = files(toolsJarFile() ?: error("tools.jar is not found!"))
fun Project.toolsJarFile(jdkHome: File = File(this.property("JDK_18") as String)): File? =
firstFromJavaHomeThatExists("lib/tools.jar", jdkHome = jdkHome)
fun Project.toolsJar(): FileCollection = files(
getToolchainLauncherFor(JdkMajorVersion.JDK_1_8)
.map {
Jvm.forHome(it.metadata.installationPath.asFile).toolsJar ?: throw GradleException("tools.jar not found!")
}
)
val compilerManifestClassPath
get() = "annotations-13.0.jar kotlin-stdlib.jar kotlin-reflect.jar kotlin-script-runtime.jar trove4j.jar"

View File

@@ -2,6 +2,8 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Project
import org.gradle.api.artifacts.DependencySubstitution
import org.gradle.api.artifacts.component.ProjectComponentSelector
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.tasks.TaskProvider
import org.gradle.jvm.tasks.Jar
@@ -80,6 +82,24 @@ private fun Project.compilerShadowJar(taskName: String, body: ShadowJar.() -> Un
}
}
fun Project.configureShadowJarSubstitutionInCompileClasspath() {
val substitutionMap = mapOf(":kotlin-reflect" to ":kotlin-reflect-api")
fun configureSubstitution(substitution: DependencySubstitution) {
val requestedProject = (substitution.requested as? ProjectComponentSelector)?.projectPath ?: return
val replacementProject = substitutionMap[requestedProject] ?: return
substitution.useTarget(project(replacementProject), "Non-default shadow jars should not be used in compile classpath")
}
sourceSets.all {
for (configName in listOf(compileOnlyConfigurationName, compileClasspathConfigurationName)) {
configurations.getByName(configName).resolutionStrategy.dependencySubstitution {
all(::configureSubstitution)
}
}
}
}
fun Project.embeddableCompiler(taskName: String = "embeddable", body: ShadowJar.() -> Unit = {}): TaskProvider<out ShadowJar> =
compilerShadowJar(taskName) {
configureEmbeddableCompilerRelocation()
@@ -93,7 +113,6 @@ fun Project.compilerDummyForDependenciesRewriting(
exclude(packagesToExcludeFromDummy)
body()
}
const val COMPILER_DUMMY_JAR_CONFIGURATION_NAME = "compilerDummyJar"
fun Project.compilerDummyJar(task: TaskProvider<out Jar>, body: Jar.() -> Unit = {}) {

View File

@@ -8,7 +8,7 @@ plugins {
kotlin("jvm")
}
publish()
publishGradlePlugin()
standardPublicJars()
extensions.extraProperties["kotlin.stdlib.default.dependency"] = "false"
@@ -42,7 +42,8 @@ tasks.withType<KotlinCompile> {
kotlinOptions.freeCompilerArgs += listOf(
"-Xskip-prerelease-check",
"-Xskip-runtime-version-check",
"-Xsuppress-version-warnings"
"-Xsuppress-version-warnings",
"-Xuse-ir" // Needed as long as languageVersion is less than 1.5.
)
}

View File

@@ -24,16 +24,16 @@ fun ProjectSettings.compiler(block: IdeaCompilerConfiguration.() -> Unit) =
fun ProjectSettings.delegateActions(block: ActionDelegationConfig.() -> Unit) =
(this@delegateActions as ExtensionAware).extensions.configure(block)
fun ProjectSettings.runConfigurations(block: DefaultRunConfigurationContainer.() -> Unit) =
fun ProjectSettings.runConfigurations(block: RunConfigurationContainer.() -> Unit) =
(this@runConfigurations as ExtensionAware).extensions.configure("runConfigurations", block)
inline fun <reified T: RunConfiguration> DefaultRunConfigurationContainer.defaults(noinline block: T.() -> Unit) =
inline fun <reified T: RunConfiguration> RunConfigurationContainer.defaults(noinline block: T.() -> Unit) =
defaults(T::class.java, block)
fun DefaultRunConfigurationContainer.junit(name: String, block: JUnit.() -> Unit) =
fun RunConfigurationContainer.junit(name: String, block: JUnit.() -> Unit) =
create(name, JUnit::class.java, block)
fun DefaultRunConfigurationContainer.application(name: String, block: Application.() -> Unit) =
fun RunConfigurationContainer.application(name: String, block: Application.() -> Unit) =
create(name, Application::class.java, block)
fun ProjectSettings.ideArtifacts(block: NamedDomainObjectContainer<org.jetbrains.gradle.ext.TopLevelArtifact>.() -> Unit) =

View File

@@ -1,198 +0,0 @@
@file:Suppress("unused") // usages in build scripts are not tracked properly
import net.rubygrapefruit.platform.Native
import net.rubygrapefruit.platform.WindowsRegistry
import org.gradle.api.GradleException
import org.gradle.api.Project
import java.nio.file.Paths
import java.io.File
import net.rubygrapefruit.platform.WindowsRegistry.Key.HKEY_LOCAL_MACHINE
import org.gradle.internal.os.OperatingSystem
enum class JdkMajorVersion(private val mandatory: Boolean = true) {
JDK_16, JDK_17, JDK_18, JDK_9, JDK_10(false), JDK_11(false), /*15.0*/JDK_15(false);
fun isMandatory(): Boolean = mandatory
}
val jdkAlternativeVarNames = mapOf(JdkMajorVersion.JDK_9 to listOf("JDK_19"), JdkMajorVersion.JDK_15 to listOf("JDK_15_0"))
data class JdkId(val explicit: Boolean, val majorVersion: JdkMajorVersion, var version: String, var homeDir: File)
fun Project.getConfiguredJdks(): List<JdkId> {
val res = arrayListOf<JdkId>()
for (jdkMajorVersion in JdkMajorVersion.values()) {
val explicitJdkEnvVal = findProperty(jdkMajorVersion.name)?.toString()
?: System.getenv(jdkMajorVersion.name)
?: jdkAlternativeVarNames[jdkMajorVersion]?.mapNotNull { System.getenv(it) }?.firstOrNull()
?: continue
val explicitJdk = Paths.get(explicitJdkEnvVal).toRealPath().toFile()
if (!explicitJdk.isDirectory) {
throw GradleException("Invalid environment value $jdkMajorVersion: $explicitJdkEnvVal, expecting JDK home path")
}
res.add(JdkId(true, jdkMajorVersion, "X", explicitJdk))
}
if (res.size < JdkMajorVersion.values().size) {
res.discoverJdks(this)
}
return res
}
// see JEP 223
private val javaMajorVersionRegex = Regex("""(?:1\.)?(\d+).*""")
private val javaVersionRegex = Regex("""(?:1\.)?(\d+)(\.\d+)?([+-_]\w+){0,3}""")
fun MutableCollection<JdkId>.addIfBetter(project: Project, version: String, id: String, homeDir: File): Boolean {
val matchString = javaMajorVersionRegex.matchEntire(version)?.groupValues?.get(1)
val majorJdkVersion = when (matchString) {
"6" -> JdkMajorVersion.JDK_16
"7" -> JdkMajorVersion.JDK_17
"8" -> JdkMajorVersion.JDK_18
"9" -> JdkMajorVersion.JDK_9
else -> {
project.logger.info("Cannot recognize version string '$version' (found version '$matchString')")
return false
}
}
val prev = find { it.majorVersion == majorJdkVersion }
if (prev == null) {
add(JdkId(false, majorJdkVersion, version, homeDir))
return true
}
if (prev.explicit) return false
val versionsComparisonRes = compareVersions(prev.version, version)
if (versionsComparisonRes < 0 || (versionsComparisonRes == 0 && id.contains("64"))) { // prefer 64-bit
prev.version = version
prev.homeDir = homeDir
return true
}
return false
}
private fun compareVersions(left: String, right: String): Int {
if (left == right) return 0
fun MatchResult.extractNumVer(): List<Int> =
groups.drop(2).map {
it?.value?.filter { it in '0'..'9' }?.toIntOrNull() ?: 0
}
val lmi = (javaVersionRegex.matchEntire(left)?.extractNumVer() ?: emptyList()).iterator()
val rmi = (javaVersionRegex.matchEntire(right)?.extractNumVer() ?: emptyList()).iterator()
while (lmi.hasNext() && rmi.hasNext()) {
val l = lmi.next()
val r = rmi.next()
when {
l < r -> return -1
l > r -> return 1
}
}
return when {
rmi.hasNext() -> -1
lmi.hasNext() -> 1
else -> 0
}
}
fun MutableCollection<JdkId>.discoverJdks(project: Project) {
val os = OperatingSystem.current()
when {
os.isWindows -> discoverJdksOnWindows(project)
os.isMacOsX -> discoverJdksOnMacOS(project)
else -> discoverJdksOnUnix(project)
}
}
private val macOsJavaHomeOutRegexes =
listOf(
Regex("""\s+(\S+),\s+(\S+):\s+".*?"\s+(.+)"""),
Regex("""\s+(\S+)\s+\((.*?)\):\s+(.+)"""),
Regex("""\s+(\S+)\s+\((.*?)\)\s+"[^"]*"\s+-\s+"[^"]*"\s(.+)"""),
Regex("""\s+(\S+)\s+\((.+)\)\s+".+"\s+-\s+".+"\s+(.+)"""))
fun MutableCollection<JdkId>.discoverJdksOnMacOS(project: Project) {
val procBuilder = ProcessBuilder("/usr/libexec/java_home", "-V").redirectErrorStream(true)
val process = procBuilder.start()
val retCode = process.waitFor()
if (retCode != 0) throw GradleException("Unable to run 'java_home', return code $retCode")
process.inputStream.bufferedReader().forEachLine { line ->
for (rex in macOsJavaHomeOutRegexes) {
val matchResult = rex.matchEntire(line)
if (matchResult != null) {
val jdkHomeDir = File(matchResult.groupValues[3])
// Filter out JRE installed at /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/
// and shown by the java_home tool
if (!jdkHomeDir.path.contains("JavaAppletPlugin.plugin")) {
addIfBetter(project, matchResult.groupValues[1], matchResult.groupValues[0], jdkHomeDir)
break
}
}
}
}
}
private val unixConventionalJdkLocations = listOf(
"/usr/lib/jvm", // *deb, Arch
"/opt", // *rpm, Gentoo, HP/UX
"/usr/lib", // Slackware 32
"/usr/lib64", // Slackware 64
"/usr/local", // OpenBSD, FreeBSD
"/usr/pkg/java", // NetBSD
"/usr/jdk/instances") // Solaris
private val unixConventionalJdkDirRex = Regex("jdk|jre|java|zulu")
fun MutableCollection<JdkId>.discoverJdksOnUnix(project: Project) {
for (loc in unixConventionalJdkLocations) {
val installedJdks = File(loc).listFiles { dir ->
dir.isDirectory &&
unixConventionalJdkDirRex.containsMatchIn(dir.name) &&
fileFrom(dir, "bin", "java").isFile
} ?: continue
for (dir in installedJdks) {
val versionMatch = javaVersionRegex.find(dir.name)
if (versionMatch == null) {
project.logger.info("Unable to extract version from possible JDK dir: $dir")
}
else {
addIfBetter(project, versionMatch.value, dir.name, dir)
}
}
}
}
private val windowsConventionalJdkRegistryPaths = listOf(
"SOFTWARE\\JavaSoft\\Java Development Kit",
"SOFTWARE\\Wow6432Node\\JavaSoft\\Java Development Kit",
"SOFTWARE\\JavaSoft\\JDK",
"SOFTWARE\\Wow6432Node\\JavaSoft\\JDK")
fun MutableCollection<JdkId>.discoverJdksOnWindows(project: Project) {
val registry = Native.get(WindowsRegistry::class.java)
for (regPath in windowsConventionalJdkRegistryPaths) {
val jdkKeys = try {
registry.getSubkeys(HKEY_LOCAL_MACHINE, regPath)
} catch (e: RuntimeException) {
// ignore missing nodes
continue
}
for (jdkKey in jdkKeys) {
try {
val javaHome = registry.getStringValue(HKEY_LOCAL_MACHINE, regPath + "\\" + jdkKey, "JavaHome")
val versionMatch = javaVersionRegex.find(jdkKey)
if (versionMatch == null) {
project.logger.info("Unable to extract version from possible JDK location: $javaHome ($jdkKey)")
}
else {
javaHome.takeIf { it.isNotEmpty() }
?.let { File(it) }
?.takeIf { it.isDirectory && fileFrom(it, "bin", "java.exe").isFile }
?.let {
addIfBetter(project, versionMatch.value, jdkKey, it)
}
}
}
catch (e: RuntimeException) {
// Ignore
}
}
}
}

View File

@@ -17,16 +17,11 @@
// usages in build scripts are not tracked properly
@file:Suppress("unused")
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.DependencyHandlerScope
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.register
import java.io.File
private fun Project.kotlinBuildLocalDependenciesDir(): File =
@@ -146,70 +141,4 @@ fun ModuleDependency.includeIntellijCoreJarDependencies(project: Project, jarsFi
rootProject = project.rootProject
)
fun Project.intellijRootDir() = IntellijRootUtils.getIntellijRootDir(project)
fun DependencyHandlerScope.excludeInAndroidStudio(rootProject: Project, block: DependencyHandlerScope.() -> Unit) {
if (!rootProject.extra.has("versions.androidStudioRelease")) {
block()
}
}
fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File, body: JavaExec.() -> Unit): TaskProvider<JavaExec> {
return tasks.register<JavaExec>(name) {
val ideaSandboxConfigDir = File(ideaSandboxDir, "config")
classpath = mainSourceSet.runtimeClasspath
mainClass.set("com.intellij.idea.Main")
workingDir = File(intellijRootDir(), "bin")
jvmArgs(
"-Xmx1250m",
"-XX:ReservedCodeCacheSize=240m",
"-XX:+HeapDumpOnOutOfMemoryError",
"-ea",
"-Didea.debug.mode=true",
"-Didea.system.path=$ideaSandboxDir",
"-Didea.config.path=$ideaSandboxConfigDir",
"-Didea.tooling.debug=true",
"-Dfus.internal.test.mode=true",
"-Dapple.laf.useScreenMenuBar=true",
"-Dapple.awt.graphics.UseQuartz=true",
"-Dsun.io.useCanonCaches=false",
"-Dplugin.path=${ideaPluginDir.absolutePath}"
)
jvmArgs("-Didea.platform.prefix=Idea")
if (rootProject.findProperty("versions.androidStudioRelease") != null) {
jvmArgs("-Didea.platform.prefix=AndroidStudio")
}
if (project.hasProperty("noPCE")) {
jvmArgs("-Didea.ProcessCanceledException=disabled")
}
jvmArgs("-Didea.is.internal=${project.findProperty("idea.is.internal") ?: true}")
project.findProperty("idea.args")?.let { arguments ->
jvmArgs(arguments.toString().split(" "))
}
args()
doFirst {
val disabledPluginsFile = File(ideaSandboxConfigDir, "disabled_plugins.txt")
val disabledPluginsContents = disabledPluginsFile.takeIf { it.isFile }?.readLines()
val filteredContents = disabledPluginsContents?.filterNot { it.contains("org.jetbrains.kotlin") }
if (filteredContents != null && filteredContents.size != disabledPluginsContents.size) {
with(disabledPluginsFile.printWriter()) {
filteredContents.forEach(this::println)
}
}
}
body()
}
}
fun Project.intellijRootDir() = IntellijRootUtils.getIntellijRootDir(project)

View File

@@ -14,6 +14,7 @@ import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.*
import plugins.KotlinBuildPublishingPlugin
import plugins.configureRepository
import plugins.mainPublicationName
import java.util.*
internal const val PLUGIN_MARKER_SUFFIX = ".gradle.plugin"
@@ -26,7 +27,7 @@ fun Project.publishPluginMarkers(withEmptyJars: Boolean = true) {
val pluginDevelopment = extensions.getByType<PluginBundleExtension>()
val publishingExtension = extensions.getByType<PublishingExtension>()
val mainPublication = publishingExtension.publications[KotlinBuildPublishingPlugin.PUBLICATION_NAME] as MavenPublication
val mainPublication = publishingExtension.publications[mainPublicationName] as MavenPublication
pluginDevelopment.plugins.forEach { declaration ->
val markerPublication = createMavenMarkerPublication(declaration, mainPublication, publishingExtension.publications)

View File

@@ -68,7 +68,7 @@ class KotlinBuildPublishingPlugin @Inject constructor(
configure<PublishingExtension> {
publications {
create<MavenPublication>(PUBLICATION_NAME) {
create<MavenPublication>(project.mainPublicationName) {
from(kotlinLibraryComponent)
configureKotlinPomAttributes(project)
@@ -79,16 +79,26 @@ class KotlinBuildPublishingPlugin @Inject constructor(
}
companion object {
const val PUBLICATION_NAME = "Main"
const val DEFAULT_MAIN_PUBLICATION_NAME = "Main"
const val MAIN_PUBLICATION_NAME_PROPERTY = "MainPublicationName"
const val REPOSITORY_NAME = "Maven"
const val ADHOC_COMPONENT_NAME = "kotlinLibrary"
const val COMPILE_CONFIGURATION = "publishedCompile"
const val RUNTIME_CONFIGURATION = "publishedRuntime"
}
}
var Project.mainPublicationName: String
get() {
return if (project.extra.has(KotlinBuildPublishingPlugin.MAIN_PUBLICATION_NAME_PROPERTY))
project.extra.get(KotlinBuildPublishingPlugin.MAIN_PUBLICATION_NAME_PROPERTY) as String
else KotlinBuildPublishingPlugin.DEFAULT_MAIN_PUBLICATION_NAME
}
set(value) {
project.extra.set(KotlinBuildPublishingPlugin.MAIN_PUBLICATION_NAME_PROPERTY, value)
}
@OptIn(ExperimentalStdlibApi::class)
private fun humanReadableName(name: String) =
name.split("-").joinToString(separator = " ") { it.capitalize(Locale.ROOT) }

View File

@@ -9,13 +9,13 @@ import org.gradle.internal.os.OperatingSystem
fun Test.configureTestDistribution(configure: TestDistributionExtension.() -> Unit = {}) {
if (extensions.findByType(TestDistributionExtension::class.java) == null) return
val isTeamcityBuild = project.kotlinBuildProperties.isTeamcityBuild
val testDistributionEnabled =
project.findProperty("kotlin.build.test.distribution.enabled")?.toString()?.toBoolean() ?: false
useJUnitPlatform()
extensions.configure(TestDistributionExtension::class.java) {
enabled.set(true)
enabled.set(testDistributionEnabled)
maxRemoteExecutors.set(20)
if (isTeamcityBuild) {
requirements.set(setOf("os=${OperatingSystem.current().familyName}"))

View File

@@ -24,7 +24,6 @@ dependencies {
testApi(projectTests(":compiler:tests-compiler-utils"))
testApi(projectTests(":compiler:tests-common-new"))
testCompile(projectTests(":jps-plugin"))
testCompile(commonDep("junit:junit"))
testCompile(intellijDep()) { includeJars("util", "idea", "idea_rt", rootProject = rootProject) }
@@ -34,6 +33,9 @@ dependencies {
testCompile(jpsStandalone()) { includeJars("jps-model") }
testCompile(jpsBuildTest())
testRuntimeOnly(compile(intellijCoreDep()) { includeJars("intellij-core") })
testRuntimeOnly(compile(intellijDep()) { includeJars("jna", rootProject = rootProject) })
testCompile("org.junit.platform:junit-platform-launcher:${commonVer("org.junit.platform", "")}")
}

View File

@@ -5,13 +5,10 @@
package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.sam.getAbstractMembers
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithNothing
import org.jetbrains.kotlin.types.KotlinType
class SamType constructor(val type: KotlinType) {
@@ -37,54 +34,3 @@ class SamType constructor(val type: KotlinType) {
}
}
open class SamTypeFactory {
fun createByValueParameter(valueParameter: ValueParameterDescriptor): SamType? {
val singleArgumentType: KotlinType
val originalSingleArgumentType: KotlinType?
val varargElementType = valueParameter.varargElementType
if (varargElementType != null) {
singleArgumentType = varargElementType
originalSingleArgumentType = valueParameter.original.varargElementType
assert(originalSingleArgumentType != null) {
"Value parameter and original value parameter have inconsistent varargs: " +
valueParameter + "; " + valueParameter.original
}
} else {
singleArgumentType = valueParameter.type
originalSingleArgumentType = valueParameter.original.type
}
if (singleArgumentType.isError || originalSingleArgumentType!!.isError) {
return null
}
// This can be true in case when the value parameter is in the method of a generic type with out-projection.
// We approximate Inv<Captured#1> to Nothing, while Inv itself can be a SAM interface safe to call here
// (see testData genericSamProjectedOut.kt for details)
// In such a case we can't have a proper supertype since wildcards are not allowed there,
// so we use Nothing arguments instead that leads to a raw type used for a SAM wrapper.
// See org.jetbrains.kotlin.codegen.state.KotlinTypeMapper#writeGenericType to understand how
// raw types and Nothing arguments relate.
val originalTypeToUse =
if (KotlinBuiltIns.isNothing(singleArgumentType))
originalSingleArgumentType.replaceArgumentsWithNothing()
else singleArgumentType
return create(originalTypeToUse.removeExternalProjections())
}
open fun isSamType(type: KotlinType): Boolean {
val descriptor = type.constructor.declarationDescriptor
return descriptor is ClassDescriptor && descriptor.isFun
}
fun create(originalType: KotlinType): SamType? {
return if (isSamType(originalType)) SamType(originalType) else null
}
private fun KotlinType.removeExternalProjections(): KotlinType {
val newArguments = arguments.map { TypeProjectionImpl(Variance.INVARIANT, it.type) }
return replace(newArguments)
}
companion object {
val INSTANCE = SamTypeFactory()
}
}

View File

@@ -0,0 +1,76 @@
/*
* 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.backend.common
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithNothing
class SamTypeApproximator(builtIns: KotlinBuiltIns, languageVersionSettings: LanguageVersionSettings) {
private val typeApproximator = TypeApproximator(builtIns, languageVersionSettings)
fun getSamTypeForValueParameter(valueParameter: ValueParameterDescriptor): KotlinType? {
val singleArgumentType: KotlinType
val originalSingleArgumentType: KotlinType?
val varargElementType = valueParameter.varargElementType
if (varargElementType != null) {
singleArgumentType = varargElementType
originalSingleArgumentType = valueParameter.original.varargElementType
assert(originalSingleArgumentType != null) {
"Value parameter and original value parameter have inconsistent varargs: " +
valueParameter + "; " + valueParameter.original
}
} else {
singleArgumentType = valueParameter.type
originalSingleArgumentType = valueParameter.original.type
}
if (singleArgumentType.isError || originalSingleArgumentType!!.isError) {
return null
}
// This can be true in case when the value parameter is in the method of a generic type with out-projection.
// We approximate Inv<Captured#1> to Nothing, while Inv itself can be a SAM interface safe to call here
// (see testData genericSamProjectedOut.kt for details)
// In such a case we can't have a proper supertype since wildcards are not allowed there,
// so we use Nothing arguments instead that leads to a raw type used for a SAM wrapper.
// See org.jetbrains.kotlin.codegen.state.KotlinTypeMapper#writeGenericType to understand how
// raw types and Nothing arguments relate.
val originalTypeToUse =
if (KotlinBuiltIns.isNothing(singleArgumentType))
originalSingleArgumentType.replaceArgumentsWithNothing()
else
singleArgumentType
val approximatedOriginalTypeToUse =
typeApproximator.approximateToSubType(
originalTypeToUse,
TypeApproximatorConfiguration.UpperBoundAwareIntersectionTypeApproximator
) ?: originalTypeToUse
approximatedOriginalTypeToUse as KotlinType
return approximatedOriginalTypeToUse.removeExternalProjections()
}
private fun KotlinType.removeExternalProjections(): KotlinType {
val newArguments = arguments.map { TypeProjectionImpl(Variance.INVARIANT, it.type) }
return replace(newArguments)
}
}
open class SamTypeFactory {
open fun isSamType(type: KotlinType): Boolean {
val descriptor = type.constructor.declarationDescriptor
return descriptor is ClassDescriptor && descriptor.isFun
}
fun create(originalType: KotlinType): SamType? {
return if (isSamType(originalType)) SamType(originalType) else null
}
}

View File

@@ -19,7 +19,9 @@ interface TypeMappingContext<Writer : JvmDescriptorTypeWriter<Type>> {
fun getClassInternalName(typeConstructor: TypeConstructorMarker): String
fun getScriptInternalName(typeConstructor: TypeConstructorMarker): String
fun Writer.writeGenericType(type: SimpleTypeMarker, asmType: Type, mode: TypeMappingMode)
// NB: The counterpart, [KotlinTypeMapper#writeGenericType], doesn't have restriction on [type]
fun Writer.writeGenericType(type: KotlinTypeMarker, asmType: Type, mode: TypeMappingMode)
}
object AbstractTypeMapper {
@@ -44,6 +46,7 @@ object AbstractTypeMapper {
sw: Writer? = null
): Type = context.typeContext.mapType(context, type, mode, sw)
// NB: The counterpart, [descriptorBasedTypeSignatureMapping#mapType] doesn't have restriction on [type].
@OptIn(ExperimentalStdlibApi::class)
private fun <Writer : JvmDescriptorTypeWriter<Type>> TypeSystemCommonBackendContextForTypeMapping.mapType(
context: TypeMappingContext<Writer>,
@@ -51,10 +54,7 @@ object AbstractTypeMapper {
mode: TypeMappingMode = TypeMappingMode.DEFAULT,
sw: Writer? = null
): Type {
if (type !is SimpleTypeMarker) {
error("Unexpected type: $type (original Kotlin type=$type of ${type.let { it::class }})")
}
if (type.isSuspendFunction()) {
if (type is SimpleTypeMarker && type.isSuspendFunction()) {
val argumentsCount = type.argumentsCount()
val argumentsList = type.asArgumentList()
@@ -79,7 +79,7 @@ object AbstractTypeMapper {
val typeConstructor = type.typeConstructor()
when {
type.isArrayOrNullableArray() -> {
type is SimpleTypeMarker && type.isArrayOrNullableArray() -> {
val typeArgument = type.asArgumentList()[0]
val (variance, memberType) = when {
typeArgument.isStarProjection() -> Variance.OUT_VARIANCE to nullableAnyType()
@@ -99,7 +99,7 @@ object AbstractTypeMapper {
return AsmUtil.getArrayType(arrayElementType)
}
typeConstructor.isClassTypeConstructor() -> {
type is SimpleTypeMarker && typeConstructor.isClassTypeConstructor() -> {
if (typeConstructor.isInlineClass() && !mode.needInlineClassWrapping) {
val expandedType = computeExpandedTypeForInlineClass(type)
require(expandedType is SimpleTypeMarker?)

View File

@@ -20,14 +20,12 @@ import org.jetbrains.kotlin.codegen.inline.NameGenerator
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.putReifiedOperationMarker
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
interface BaseExpressionCodegen {
val frameMap: FrameMapBase<*>
val visitor: InstructionAdapter
@@ -40,24 +38,14 @@ interface BaseExpressionCodegen {
fun propagateChildReifiedTypeParametersUsages(reifiedTypeParametersUsages: ReifiedTypeParametersUsages)
fun pushClosureOnStack(
classDescriptor: ClassDescriptor,
putThis: Boolean,
callGenerator: CallGenerator,
functionReferenceReceiver: StackValue?
)
fun markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards: Boolean)
fun consumeReifiedOperationMarker(typeParameter: TypeParameterMarker)
fun putReifiedOperationMarkerIfTypeIsReifiedParameter(type: KotlinTypeMarker, operationKind: OperationKind) {
with(typeSystem) {
val (typeParameter, second) = extractReificationArgument(type) ?: return
if (typeParameter.isReified()) {
consumeReifiedOperationMarker(typeParameter)
putReifiedOperationMarker(operationKind, second, visitor)
}
}
}
}
fun BaseExpressionCodegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(type: KotlinTypeMarker, operationKind: OperationKind): Boolean {
val (typeParameter, second) = typeSystem.extractReificationArgument(type) ?: return false
consumeReifiedOperationMarker(typeParameter)
putReifiedOperationMarker(operationKind, second, visitor)
return true
}

View File

@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.types.upperIfFlexible
import org.jetbrains.org.objectweb.asm.Type
@@ -51,7 +52,7 @@ class CallBasedArgumentGenerator(
callGenerator.putValueIfNeeded(
getJvmKotlinType(i),
StackValue.createDefaultValue(valueParameterTypes[i]),
ValueKind.DEFAULT_PARAMETER,
if (InlineUtil.isInlineParameter(valueParameters[i])) ValueKind.DEFAULT_INLINE_PARAMETER else ValueKind.DEFAULT_PARAMETER,
i
)
}

View File

@@ -15,10 +15,9 @@ enum class ValueKind {
GENERAL,
GENERAL_VARARG,
DEFAULT_PARAMETER,
DEFAULT_INLINE_PARAMETER,
DEFAULT_MASK,
METHOD_HANDLE_IN_DEFAULT,
CAPTURED,
DEFAULT_LAMBDA_CAPTURED_PARAMETER,
NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND,
NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER
}
@@ -40,13 +39,9 @@ interface CallGenerator {
}
}
override fun processAndPutHiddenParameters(justProcess: Boolean) {
override fun processHiddenParameters() {}
}
override fun putHiddenParamsIntoLocals() {
}
override fun putHiddenParamsIntoLocals() {}
override fun genValueAndPut(
valueParameterDescriptor: ValueParameterDescriptor?,
@@ -141,9 +136,8 @@ interface CallGenerator {
paramIndex: Int
)
fun processAndPutHiddenParameters(justProcess: Boolean)
fun processHiddenParameters()
/*should be called if justProcess = true in processAndPutHiddenParameters*/
fun putHiddenParamsIntoLocals()
fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>)

View File

@@ -27,24 +27,16 @@ import org.jetbrains.annotations.TestOnly;
import org.jetbrains.kotlin.backend.common.output.OutputFile;
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.config.AnalysisFlags;
import org.jetbrains.kotlin.config.JvmAnalysisFlags;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.DescriptorUtilKt;
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.load.kotlin.ModuleMappingUtilKt;
import org.jetbrains.kotlin.metadata.ProtoBuf;
import org.jetbrains.kotlin.metadata.jvm.JvmModuleProtoBuf;
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping;
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMappingKt;
import org.jetbrains.kotlin.metadata.jvm.deserialization.PackageParts;
import org.jetbrains.kotlin.metadata.serialization.StringTable;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.serialization.StringTableImpl;
import org.jetbrains.org.objectweb.asm.Type;
@@ -52,7 +44,6 @@ import org.jetbrains.org.objectweb.asm.Type;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.getMappingFileName;
@@ -134,11 +125,6 @@ public class ClassFileFactory implements OutputFileCollection {
StringTableImpl stringTable = new StringTableImpl();
ClassFileUtilsKt.addDataFromCompiledModule(builder, packagePartRegistry, stringTable, state);
List<String> experimental = state.getLanguageVersionSettings().getFlag(AnalysisFlags.getExperimental());
if (!experimental.isEmpty()) {
writeExperimentalMarkers(state.getModule(), builder, experimental, stringTable);
}
Pair<ProtoBuf.StringTable, ProtoBuf.QualifiedNameTable> tables = stringTable.buildProto();
builder.setStringTable(tables.getFirst());
builder.setQualifiedNameTable(tables.getSecond());
@@ -162,26 +148,6 @@ public class ClassFileFactory implements OutputFileCollection {
});
}
private static void writeExperimentalMarkers(
@NotNull ModuleDescriptor module,
@NotNull JvmModuleProtoBuf.Module.Builder builder,
@NotNull List<String> experimental,
@NotNull StringTable stringTable
) {
for (String fqName : experimental) {
ClassDescriptor descriptor =
DescriptorUtilKt.resolveClassByFqName(module, new FqName(fqName), NoLookupLocation.FOR_ALREADY_TRACKED);
if (descriptor != null) {
ProtoBuf.Annotation.Builder annotation = ProtoBuf.Annotation.newBuilder();
ClassId classId = DescriptorUtilsKt.getClassId(descriptor);
if (classId != null) {
annotation.setId(stringTable.getQualifiedClassNameIndex(classId.asString(), false));
builder.addAnnotation(annotation);
}
}
}
}
@NotNull
@Override
public List<OutputFile> asList() {

View File

@@ -6,19 +6,17 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.inline.InlineCodegen
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
import org.jetbrains.kotlin.codegen.inline.loadCompiledInlineFunction
import org.jetbrains.kotlin.codegen.optimization.nullCheck.usesLocalExceptParameterNullCheck
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.FunctionImportedFromObject
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
class DelegatedPropertiesCodegenHelper(private val state: GenerationState) {
@@ -65,27 +63,15 @@ class DelegatedPropertiesCodegenHelper(private val state: GenerationState) {
this
private fun isDelegatedPropertyMetadataRequiredForFunctionFromBinaries(calleeDescriptor: FunctionDescriptor): Boolean {
assert(calleeDescriptor is DescriptorWithContainerSource) {
require(calleeDescriptor is DescriptorWithContainerSource) {
"Function descriptor from binaries expected: $calleeDescriptor"
}
val metadataParameterIndex = getMetadataParameterIndex(calleeDescriptor)
val methodNode = InlineCodegen.createSpecialInlineMethodNodeFromBinaries(calleeDescriptor, state)
return isMetadataParameterUsedInCompiledMethodBody(metadataParameterIndex, methodNode)
}
private fun isMetadataParameterUsedInCompiledMethodBody(metadataParameterIndex: Int, methodNode: MethodNode): Boolean =
methodNode.instructions.toArray().any { insn ->
insn is VarInsnNode && insn.opcode == Opcodes.ALOAD && insn.`var` == metadataParameterIndex &&
!isParameterNullCheckArgument(insn)
}
private fun isParameterNullCheckArgument(insn: AbstractInsnNode): Boolean {
val next1 = insn.next
val next2 = next1.next
return next1 != null && next2 != null &&
next1.opcode == Opcodes.LDC && next2.isCheckParameterIsNotNull()
val containerId = KotlinTypeMapper.getContainingClassesForDeserializedCallable(calleeDescriptor).implClassId
val asmMethod = state.typeMapper.mapAsmMethod(calleeDescriptor)
val isMangled = requiresFunctionNameManglingForReturnType(calleeDescriptor)
val methodNode = loadCompiledInlineFunction(containerId, asmMethod, calleeDescriptor.isSuspend, isMangled, state).node
return methodNode.usesLocalExceptParameterNullCheck(metadataParameterIndex)
}
private fun getMetadataParameterIndex(calleeDescriptor: FunctionDescriptor): Int {

View File

@@ -107,6 +107,7 @@ import java.util.stream.Collectors;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isInt;
import static org.jetbrains.kotlin.codegen.AsmUtil.boxType;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.BaseExpressionCodegenKt.putReifiedOperationMarkerIfTypeIsReifiedParameter;
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.*;
import static org.jetbrains.kotlin.codegen.DescriptorAsmUtil.boxType;
import static org.jetbrains.kotlin.codegen.DescriptorAsmUtil.*;
@@ -1261,9 +1262,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (closure.isSuspendLambda()) {
// When inlining crossinline lambda, the ACONST_NULL is never popped.
// Thus, do not generate it. Otherwise, it leads to VerifyError on run-time.
boolean isCrossinlineLambda = (callGenerator instanceof InlineCodegen<?>) &&
Objects.requireNonNull(((InlineCodegen) callGenerator).getActiveLambda(),
"no active lambda found").isCrossInline;
boolean isCrossinlineLambda = (callGenerator instanceof PsiInlineCodegen) &&
Objects.requireNonNull(((PsiInlineCodegen) callGenerator).getActiveLambda(),
"no active lambda found").isCrossInline();
if (!isCrossinlineLambda) {
v.aconst(null);
}
@@ -2780,7 +2781,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, maybeSuspensionPoint, isConstructor);
}
callGenerator.processAndPutHiddenParameters(false);
callGenerator.processHiddenParameters();
callGenerator.putHiddenParamsIntoLocals();
List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor();
@@ -2949,13 +2951,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
bindingContext, state
);
PsiSourceCompilerForInline sourceCompiler = new PsiSourceCompilerForInline(this, callElement);
FunctionDescriptor functionDescriptor =
InlineUtil.isArrayConstructorWithLambda(original)
? FictitiousArrayConstructor.create((ConstructorDescriptor) original) : original.getOriginal();
PsiSourceCompilerForInline sourceCompiler = new PsiSourceCompilerForInline(this, callElement, functionDescriptor);
sourceCompiler.initializeInlineFunctionContext(functionDescriptor);
JvmMethodSignature signature = typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompiler.getContextKind());
JvmMethodSignature signature = typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompiler.getContext().getContextKind());
if (signature.getAsmMethod().getName().contains("-") &&
!state.getConfiguration().getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME)
) {
@@ -2963,17 +2964,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
InlineClassesCodegenUtilKt.classFileContainsMethod(functionDescriptor, state, signature.getAsmMethod());
if (classFileContainsMethod != null && !classFileContainsMethod) {
typeMapper.setUseOldManglingRulesForFunctionAcceptingInlineClass(true);
signature = typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompiler.getContextKind());
signature = typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompiler.getContext().getContextKind());
typeMapper.setUseOldManglingRulesForFunctionAcceptingInlineClass(false);
}
}
Type methodOwner = typeMapper.mapImplementationOwner(functionDescriptor);
if (isDefaultCompilation) {
return new InlineCodegenForDefaultBody(functionDescriptor, this, state, methodOwner, signature, sourceCompiler);
}
else {
return new PsiInlineCodegen(this, state, functionDescriptor, methodOwner, signature, typeParameterMappings, sourceCompiler,
typeMapper.mapOwner(descriptor));
return new InlineCodegenForDefaultBody(functionDescriptor, this, state, signature, sourceCompiler);
} else {
return new PsiInlineCodegen(
this, state, functionDescriptor, signature, typeParameterMappings, sourceCompiler,
typeMapper.mapImplementationOwner(functionDescriptor), typeMapper.mapOwner(descriptor), callElement
);
}
}
@@ -3557,7 +3558,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (TypeUtils.isTypeParameter(type)) {
assert TypeUtils.isReifiedTypeParameter(type) :
"Non-reified type parameter under ::class should be rejected by type checker: " + type;
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS);
putReifiedOperationMarkerIfTypeIsReifiedParameter(this, type, ReifiedTypeInliner.OperationKind.JAVA_CLASS);
}
putJavaLangClassInstance(v, typeMapper.mapType(type), type, typeMapper);
@@ -4930,10 +4931,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
public void newArrayInstruction(@NotNull KotlinType arrayType) {
if (KotlinBuiltIns.isArray(arrayType)) {
KotlinType elementJetType = arrayType.getArguments().get(0).getType();
putReifiedOperationMarkerIfTypeIsReifiedParameter(
elementJetType,
ReifiedTypeInliner.OperationKind.NEW_ARRAY
);
putReifiedOperationMarkerIfTypeIsReifiedParameter(this, elementJetType, ReifiedTypeInliner.OperationKind.NEW_ARRAY);
v.newarray(boxType(typeMapper.mapTypeAsDeclaration(elementJetType)));
}
else {
@@ -5237,7 +5235,7 @@ The "returned" value of try expression with no finally is either the last expres
boolean safeAs = opToken == KtTokens.AS_SAFE;
if (TypeUtils.isReifiedTypeParameter(rightKotlinType)) {
putReifiedOperationMarkerIfTypeIsReifiedParameter(rightKotlinType,
putReifiedOperationMarkerIfTypeIsReifiedParameter(this, rightKotlinType,
safeAs ? ReifiedTypeInliner.OperationKind.SAFE_AS
: ReifiedTypeInliner.OperationKind.AS);
v.checkcast(boxedRightType);
@@ -5294,7 +5292,7 @@ The "returned" value of try expression with no finally is either the last expres
Type type = boxType(typeMapper.mapTypeAsDeclaration(rhsKotlinType));
if (TypeUtils.isReifiedTypeParameter(rhsKotlinType)) {
putReifiedOperationMarkerIfTypeIsReifiedParameter(rhsKotlinType, ReifiedTypeInliner.OperationKind.IS);
putReifiedOperationMarkerIfTypeIsReifiedParameter(this, rhsKotlinType, ReifiedTypeInliner.OperationKind.IS);
v.instanceOf(type);
return null;
}
@@ -5546,11 +5544,4 @@ The "returned" value of try expression with no finally is either the last expres
parentCodegen.getReifiedTypeParametersUsages().addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
}
}
@Override
public void putReifiedOperationMarkerIfTypeIsReifiedParameter(
@NotNull KotlinTypeMarker type, @NotNull ReifiedTypeInliner.OperationKind operationKind
) {
BaseExpressionCodegen.DefaultImpls.putReifiedOperationMarkerIfTypeIsReifiedParameter(this, type, operationKind);
}
}

View File

@@ -68,6 +68,13 @@ open class FrameMapBase<T : Any> {
return Mark(currentSize)
}
fun skipTo(target: Int): Mark {
return mark().also {
if (currentSize < target)
currentSize = target
}
}
inner class Mark(private val myIndex: Int) {
fun dropTo() {

View File

@@ -5,10 +5,11 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.backend.common.SamTypeFactory
import org.jetbrains.kotlin.load.java.sam.JavaSingleAbstractMethodUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.backend.common.SamTypeFactory
object JvmSamTypeFactory : SamTypeFactory() {
override fun isSamType(type: KotlinType) = JavaSingleAbstractMethodUtils.isSamType(type)
class JvmSamTypeFactory : SamTypeFactory() {
override fun isSamType(type: KotlinType) =
JavaSingleAbstractMethodUtils.isSamType(type)
}

View File

@@ -45,7 +45,6 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.SimpleType;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.model.KotlinTypeMarker;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.Opcodes;
@@ -1329,8 +1328,8 @@ public abstract class StackValue {
StackValue newReceiver = StackValue.receiver(call, receiver, codegen, callable);
ArgumentGenerator generator = createArgumentGenerator();
newReceiver.put(newReceiver.type, newReceiver.kotlinType, v);
callGenerator.processAndPutHiddenParameters(false);
callGenerator.processHiddenParameters();
callGenerator.putHiddenParamsIntoLocals();
defaultArgs = generator.generate(valueArguments, valueArguments, call.getResultingDescriptor());
}
@@ -1748,7 +1747,8 @@ public abstract class StackValue {
assert getterDescriptor != null : "Getter descriptor should be not null for " + descriptor;
if (resolvedCall != null && getterDescriptor.isInline()) {
CallGenerator callGenerator = codegen.getOrCreateCallGenerator(resolvedCall, ((PropertyDescriptor)resolvedCall.getResultingDescriptor()).getGetter());
callGenerator.processAndPutHiddenParameters(false);
callGenerator.processHiddenParameters();
callGenerator.putHiddenParamsIntoLocals();
callGenerator.genCall(getter, resolvedCall, false, codegen);
}
else {
@@ -1832,7 +1832,7 @@ public abstract class StackValue {
if (!skipReceiver) {
putReceiver(v, false);
}
callGenerator.processAndPutHiddenParameters(true);
callGenerator.processHiddenParameters();
callGenerator.putValueIfNeeded(new JvmKotlinType(
CollectionsKt.last(setter.getValueParameters()).getAsmType(),
CollectionsKt.last(setterDescriptor.getValueParameters()).getType()),

View File

@@ -22,7 +22,9 @@ import java.lang.StringBuilder
class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapter) {
private val template = StringBuilder("")
private val specialSymbolsInTemplate = arrayListOf<String>()
private val paramTypes = arrayListOf<Type>()
private var paramSlots = 0
private var justFlushed = false
@JvmOverloads
@@ -42,7 +44,16 @@ class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapte
if (mode == JvmStringConcat.INDY_WITH_CONSTANTS) {
when (stackValue) {
is StackValue.Constant -> {
template.append(stackValue.value)
val value = stackValue.value
if (value is String && (value.contains("\u0001") || value.contains("\u0002"))) {
template.append("\u0002") //reference to special symbols added on next line
specialSymbolsInTemplate.add(value)
} else if (value is Char && (value == 1.toChar() || value == 2.toChar())) {
template.append("\u0002") //reference to special symbols added on next line
specialSymbolsInTemplate.add(value.toString())
} else {
template.append(value)
}
return
}
TRUE -> {
@@ -74,8 +85,9 @@ class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapte
} else {
justFlushed = false
paramTypes.add(type)
paramSlots += type.size
template.append("\u0001")
if (paramTypes.size == 200) {
if (paramSlots >= 200) {
// Concatenate current arguments into string
// because of `StringConcatFactory` limitation add use it as new argument for further processing:
// "The number of parameter slots in {@code concatType} is less than or equal to 200"
@@ -104,7 +116,7 @@ class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapte
"makeConcatWithConstants",
Type.getMethodDescriptor(JAVA_STRING_TYPE, *paramTypes.toTypedArray()),
bootstrap,
arrayOf(template.toString())
arrayOf(template.toString()) + specialSymbolsInTemplate
)
} else {
val bootstrap = Handle(
@@ -122,10 +134,15 @@ class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapte
arrayOf()
)
}
//clear old template
template.clear()
specialSymbolsInTemplate.clear()
paramTypes.clear()
//add just flushed string
paramTypes.add(JAVA_STRING_TYPE)
template.append("\u0001")
paramSlots = JAVA_STRING_TYPE.size
}
}

View File

@@ -15,6 +15,7 @@ import kotlin.Pair;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.SamTypeApproximator;
import org.jetbrains.kotlin.builtins.FunctionTypesKt;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.ReflectionTypes;
@@ -34,6 +35,7 @@ import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
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.psi.*;
@@ -90,6 +92,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
private final ClassBuilderMode classBuilderMode;
private final DelegatedPropertiesCodegenHelper delegatedPropertiesCodegenHelper;
private final JvmDefaultMode jvmDefaultMode;
private final SamTypeApproximator samTypeApproximator;
public CodegenAnnotatingVisitor(@NotNull GenerationState state) {
this.bindingTrace = state.getBindingTrace();
@@ -100,7 +103,8 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
this.languageVersionSettings = state.getLanguageVersionSettings();
this.classBuilderMode = state.getClassBuilderMode();
this.delegatedPropertiesCodegenHelper = new DelegatedPropertiesCodegenHelper(state);
jvmDefaultMode = state.getJvmDefaultMode();
this.jvmDefaultMode = state.getJvmDefaultMode();
this.samTypeApproximator = new SamTypeApproximator(state.getModule().getBuiltIns(), state.getLanguageVersionSettings());
}
@NotNull
@@ -855,6 +859,20 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
}
}
@Nullable
private SamType createSamType(KotlinType kotlinType) {
if (!JavaSingleAbstractMethodUtils.isSamType(kotlinType)) return null;
return new SamType(kotlinType);
}
@Nullable
private SamType createSamTypeByValueParameter(ValueParameterDescriptor valueParameterDescriptor) {
KotlinType kotlinSamType = samTypeApproximator.getSamTypeForValueParameter(valueParameterDescriptor);
if (kotlinSamType == null) return null;
if (!JavaSingleAbstractMethodUtils.isSamType(kotlinSamType)) return null;
return new SamType(kotlinSamType);
}
private void writeSamValueForValueParameters(
@NotNull Collection<ValueParameterDescriptor> valueParametersWithSAMConversion,
@Nullable List<ResolvedValueArgument> valueArguments
@@ -862,7 +880,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
if (valueArguments == null) return;
for (ValueParameterDescriptor valueParameter : valueParametersWithSAMConversion) {
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(valueParameter);
SamType samType = createSamTypeByValueParameter(valueParameter);
if (samType == null) continue;
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
@@ -874,7 +892,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
}
private void recordSamTypeOnArgumentExpression(ValueParameterDescriptor valueParameter, ValueArgument valueArgument) {
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(valueParameter);
SamType samType = createSamTypeByValueParameter(valueParameter);
if (samType == null) return;
recordSamTypeOnArgumentExpression(samType, valueArgument);
@@ -955,8 +973,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
KtExpression argumentExpression = argument.getArgumentExpression();
bindingTrace.record(SAM_CONSTRUCTOR_TO_ARGUMENT, expression, argumentExpression);
//noinspection ConstantConditions
SamType samType = JvmSamTypeFactory.INSTANCE.create(callableDescriptor.getReturnType());
SamType samType = createSamType(callableDescriptor.getReturnType());
bindingTrace.record(SAM_VALUE, argumentExpression, samType);
}
@@ -973,7 +990,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter((FunctionDescriptor) operationDescriptor);
if (original == null) return;
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(original.getValueParameters().get(0));
SamType samType = createSamTypeByValueParameter(original.getValueParameters().get(0));
if (samType == null) return;
IElementType token = expression.getOperationToken();
@@ -1002,7 +1019,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
List<KtExpression> indexExpressions = expression.getIndexExpressions();
List<ValueParameterDescriptor> parameters = original.getValueParameters();
for (ValueParameterDescriptor valueParameter : parameters) {
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(valueParameter);
SamType samType = createSamTypeByValueParameter(valueParameter);
if (samType == null) continue;
if (isSetter && valueParameter.getIndex() == parameters.size() - 1) {

View File

@@ -393,13 +393,12 @@ fun TypeSystemCommonBackendContext.extractReificationArgument(initialType: Kotli
while (type.isArrayOrNullableArray()) {
arrayDepth++
val argument = type.getArgument(0)
type =
if (argument.isStarProjection()) nullableAnyType()
else argument.getType()
if (argument.isStarProjection()) return null
type = argument.getType()
}
val typeParameter = type.typeConstructor().getTypeParameterClassifier() ?: return null
if (!typeParameter.isReified()) return null
return Pair(typeParameter, ReificationArgument(typeParameter.getName().asString(), isNullable, arrayDepth))
}

View File

@@ -136,8 +136,6 @@ class CoroutineTransformerMethodVisitor(
UninitializedStoresProcessor(methodNode, shouldPreserveClassInitialization).run()
updateLvtAccordingToLiveness(methodNode, isForNamedFunction)
val spilledToVariableMapping = spillVariables(suspensionPoints, methodNode)
val suspendMarkerVarIndex = methodNode.maxLocals++
@@ -194,6 +192,8 @@ class CoroutineTransformerMethodVisitor(
dropUnboxInlineClassMarkers(methodNode, suspensionPoints)
methodNode.removeEmptyCatchBlocks()
updateLvtAccordingToLiveness(methodNode, isForNamedFunction)
if (languageVersionSettings.isReleaseCoroutines()) {
writeDebugMetadata(methodNode, suspensionPointLineNumbers, spilledToVariableMapping)
}
@@ -791,19 +791,30 @@ class CoroutineTransformerMethodVisitor(
// Mutate method node
fun generateSpillAndUnspill(suspension: SuspensionPoint, slot: Int, spillableVariable: SpillableVariable?) {
if (spillableVariable == null) {
with(instructions) {
insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter {
aconst(null)
store(slot, AsmTypes.OBJECT_TYPE)
})
fun splitLvtRecord(local: LocalVariableNode?, localRestart: LabelNode) {
// Split the local variable range for the local so that it is visible until the next state label, but is
// not visible until it has been unspilled from the continuation on the reentry path.
if (local != null) {
val previousEnd = local.end
local.end = suspension.stateLabel
// Add the local back, but end it at the next state label.
methodNode.localVariables.add(local)
// Add a new entry that starts after the local variable is restored from the continuation.
methodNode.localVariables.add(
LocalVariableNode(
local.name,
local.desc,
local.signature,
localRestart,
previousEnd,
local.index
)
)
}
return
}
// Find and remove the local variable node, if any, in the local variable table corresponding to the slot that is spilled.
var local: LocalVariableNode? = null
val localRestart = LabelNode().linkWithLabel()
val iterator = methodNode.localVariables.listIterator()
while (iterator.hasNext()) {
val node = iterator.next()
@@ -817,6 +828,19 @@ class CoroutineTransformerMethodVisitor(
}
}
if (spillableVariable == null) {
with(instructions) {
insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter {
aconst(null)
store(slot, AsmTypes.OBJECT_TYPE)
})
}
val newStart = suspension.tryCatchBlocksContinuationLabel.findNextOrNull { it is LabelNode } as? LabelNode ?: return
splitLvtRecord(local, newStart)
return
}
val localRestart = LabelNode().linkWithLabel()
with(instructions) {
// store variable before suspension call
insertBefore(suspension.suspensionCallBegin, withInstructionAdapter {
@@ -846,25 +870,7 @@ class CoroutineTransformerMethodVisitor(
})
}
// Split the local variable range for the local so that it is visible until the next state label, but is
// not visible until it has been unspilled from the continuation on the reentry path.
if (local != null) {
val previousEnd = local.end
local.end = suspension.stateLabel
// Add the local back, but end it at the next state label.
methodNode.localVariables.add(local)
// Add a new entry that starts after the local variable is restored from the continuation.
methodNode.localVariables.add(
LocalVariableNode(
local.name,
local.desc,
local.signature,
localRestart,
previousEnd,
local.index
)
)
}
splitLvtRecord(local, localRestart)
}
fun cleanUpField(suspension: SuspensionPoint, fieldIndex: Int) {
@@ -1254,6 +1260,9 @@ internal fun replaceFakeContinuationsWithRealOnes(methodNode: MethodNode, contin
}
}
private fun MethodNode.nodeTextWithLiveness(liveness: List<VariableLivenessFrame>): String =
liveness.zip(this.instructions.asSequence().toList()).joinToString("\n") { (a, b) -> "$a|${b.insnText}" }
/* We do not want to spill dead variables, thus, we shrink its LVT record to region, where the variable is alive,
* so, the variable will not be visible in debugger. User can still prolong life span of the variable by using it.
*
@@ -1288,9 +1297,6 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
fun min(a: LabelNode, b: LabelNode): LabelNode =
if (method.instructions.indexOf(a) < method.instructions.indexOf(b)) a else b
fun max(a: LabelNode, b: LabelNode): LabelNode =
if (method.instructions.indexOf(a) < method.instructions.indexOf(b)) b else a
val oldLvt = arrayListOf<LocalVariableNode>()
for (record in method.localVariables) {
oldLvt += record
@@ -1298,7 +1304,6 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
method.localVariables.clear()
// Skip `this` for suspend lambda
val start = if (isForNamedFunction) 0 else 1
val oldLvtNodeToLatestNewLvtNode = mutableMapOf<LocalVariableNode, LocalVariableNode>()
for (variableIndex in start until method.maxLocals) {
if (oldLvt.none { it.index == variableIndex }) continue
var startLabel: LabelNode? = null
@@ -1310,7 +1315,7 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
if (isAlive(insnIndex, variableIndex) && !isAlive(insnIndex + 1, variableIndex)) {
// No variable in LVT -> do not add one
val lvtRecord = oldLvt.findRecord(insnIndex, variableIndex) ?: continue
if (lvtRecord.name == CONTINUATION_VARIABLE_NAME) continue
if (lvtRecord.name == CONTINUATION_VARIABLE_NAME || lvtRecord.name == SUSPEND_CALL_RESULT_NAME) continue
// End the local when it is no longer live. Since it is not live, we will not spill and unspill it across
// suspension points. It is tempting to keep it alive until the next suspension point to leave it visible in
// the debugger for as long as possible. However, in the case of loops, the resumption after suspension can
@@ -1337,14 +1342,32 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
// startLabel can be null in case of parameters
@Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start
val node = LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
if (lvtRecord !in oldLvtNodeToLatestNewLvtNode) {
method.localVariables.add(node)
}
oldLvtNodeToLatestNewLvtNode[lvtRecord] = node
method.localVariables.add(node)
}
}
}
// Merge consequent LVT records, otherwise, atomicfu goes crazy (KT-47749)
val toRemove = arrayListOf<LocalVariableNode>()
val sortedLVT = method.localVariables.sortedBy { method.instructions.indexOf(it.start) }
for (i in sortedLVT.indices) {
var endIndex = method.instructions.indexOf(sortedLVT[i].end)
for (j in (i + 1) until sortedLVT.size) {
val startIndex = method.instructions.indexOf(sortedLVT[j].start)
if (endIndex < startIndex) break
if (endIndex != startIndex ||
sortedLVT[i].index != sortedLVT[j].index ||
sortedLVT[i].name != sortedLVT[j].name ||
sortedLVT[i].desc != sortedLVT[j].desc
) continue
sortedLVT[i].end = sortedLVT[j].end
endIndex = method.instructions.indexOf(sortedLVT[j].end)
toRemove += sortedLVT[j]
}
}
method.localVariables.removeAll(toRemove)
for (variable in oldLvt) {
// $continuation and $result are dead, but they are used by debugger, as well as fake inliner variables
// For example, $continuation is used to create async stack trace

View File

@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.codegen.optimization.boxing.isUnitInstance
import org.jetbrains.kotlin.codegen.optimization.common.MethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.removeAll
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
@@ -85,7 +85,7 @@ private class UnitSourceInterpreter(private val localVariables: Set<Int>) : Basi
}
fun run(internalClassName: String, methodNode: MethodNode): Array<Frame<BasicValue>?> {
val frames = MethodAnalyzer<BasicValue>(internalClassName, methodNode, this).analyze()
val frames = FastMethodAnalyzer<BasicValue>(internalClassName, methodNode, this).analyze()
// The ASM analyzer does not visit POP instructions, so we do so here.
for ((insn, frame) in methodNode.instructions.asSequence().zip(frames.asSequence())) {
if (frame != null && insn.opcode == Opcodes.POP) {

View File

@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.optimization.common.MethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -130,11 +130,11 @@ internal fun performSpilledVariableFieldTypesAnalysis(
thisName: String
): Array<out Frame<BasicValue>?> {
val interpreter = IntLikeCoerceInterpreter()
MethodAnalyzer(thisName, methodNode, interpreter).analyze()
FastMethodAnalyzer(thisName, methodNode, interpreter).analyze()
for ((insn, type) in interpreter.needsToBeCoerced) {
methodNode.instructions.insert(insn, withInstructionAdapter { coerceInt(type, this) })
}
return MethodAnalyzer(thisName, methodNode, OptimizationBasicInterpreter()).analyze()
return FastMethodAnalyzer(thisName, methodNode, OptimizationBasicInterpreter()).analyze()
}
private fun coerceInt(to: Type, v: InstructionAdapter) {

View File

@@ -159,8 +159,8 @@ internal class MethodNodeExaminer(
* @return indices of safely reachable returns for each instruction in the method node
*/
private fun findSafelyReachableReturns(): Array<Set<Int>?> {
val insns = methodNode.instructions
val reachableReturnsIndices = Array(insns.size()) init@{ index ->
val insns = methodNode.instructions.toArray()
val reachableReturnsIndices = Array(insns.size) init@{ index ->
val insn = insns[index]
if (insn.opcode == Opcodes.ARETURN && !insn.isAreturnAfterSafeUnitInstance()) {
@@ -182,7 +182,7 @@ internal class MethodNodeExaminer(
var changed: Boolean
do {
changed = false
for (index in 0 until insns.size()) {
for (index in insns.indices.reversed()) {
if (insns[index].opcode == Opcodes.ARETURN) continue
@Suppress("RemoveExplicitTypeArguments")

View File

@@ -73,8 +73,8 @@ import kotlin.math.max
* - restore constructor arguments
*/
class UninitializedStoresProcessor(
private val methodNode: MethodNode,
private val shouldPreserveClassInitialization: Boolean
private val methodNode: MethodNode,
private val shouldPreserveClassInitialization: Boolean
) {
// <init> method is "special", because it will invoke <init> from this class or from a base class for #0
//
@@ -87,10 +87,10 @@ class UninitializedStoresProcessor(
fun run() {
val interpreter = UninitializedNewValueMarkerInterpreter(methodNode.instructions)
val frames = CustomFramesMethodAnalyzer(
"fake", methodNode, interpreter,
this::UninitializedNewValueFrame
).analyze()
if (methodNode.instructions.toArray().none { it.opcode == Opcodes.NEW })
return
val frames = CustomFramesMethodAnalyzer("fake", methodNode, interpreter, this::UninitializedNewValueFrame).analyze()
interpreter.analyzePopInstructions(frames)
@@ -115,12 +115,12 @@ class UninitializedStoresProcessor(
// POP
val typeNameForClass = newInsn.desc.replace('/', '.')
insertBefore(newInsn, LdcInsnNode(typeNameForClass))
insertBefore(newInsn, MethodInsnNode(
Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false
))
insertBefore(
newInsn,
MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false)
)
set(newInsn, InsnNode(Opcodes.POP))
}
else {
} else {
remove(newInsn)
}
}
@@ -138,10 +138,7 @@ class UninitializedStoresProcessor(
}
methodNode.maxLocals = max(methodNode.maxLocals, nextVarIndex)
methodNode.instructions.insertBefore(insn, insnListOf(
TypeInsnNode(Opcodes.NEW, newInsn.desc),
InsnNode(Opcodes.DUP)
))
methodNode.instructions.insertBefore(insn, insnListOf(TypeInsnNode(Opcodes.NEW, newInsn.desc), InsnNode(Opcodes.DUP)))
for (type in storedTypes.reversed()) {
nextVarIndex -= type.size
@@ -174,11 +171,10 @@ class UninitializedStoresProcessor(
assert(insn.opcode == Opcodes.INVOKESPECIAL) { "Expected opcode Opcodes.INVOKESPECIAL for <init>, but ${insn.opcode} found" }
val paramsCountIncludingReceiver = Type.getArgumentTypes((insn as MethodInsnNode).desc).size + 1
val newValue = peek(paramsCountIncludingReceiver) as? UninitializedNewValue ?:
if (isInSpecialMethod)
return null
else
error("Expected value generated with NEW")
val newValue = peek(paramsCountIncludingReceiver) as? UninitializedNewValue ?: if (isInSpecialMethod)
return null
else
error("Expected value generated with NEW")
assert(peek(paramsCountIncludingReceiver - 1) is UninitializedNewValue) {
"Next value after NEW should be one generated by DUP"
@@ -188,8 +184,8 @@ class UninitializedStoresProcessor(
}
private class UninitializedNewValue(
val newInsn: TypeInsnNode,
val internalName: String
val newInsn: TypeInsnNode,
val internalName: String
) : StrictBasicValue(Type.getObjectType(internalName)) {
override fun toString() = "UninitializedNewValue(internalName='$internalName')"
}
@@ -236,7 +232,8 @@ class UninitializedStoresProcessor(
private fun checkUninitializedObjectCopy(newInsn: TypeInsnNode, usageInsn: AbstractInsnNode) {
when (usageInsn.opcode) {
Opcodes.DUP, Opcodes.ASTORE, Opcodes.ALOAD -> {}
Opcodes.DUP, Opcodes.ASTORE, Opcodes.ALOAD -> {
}
else -> error("Unexpected copy instruction for ${newInsn.debugText}: ${usageInsn.debugText}")
}
}

View File

@@ -9,7 +9,6 @@ import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.coroutines.DEBUG_METADATA_ANNOTATION_ASM_TYPE
import org.jetbrains.kotlin.codegen.coroutines.isCoroutineSuperClass
import org.jetbrains.kotlin.codegen.coroutines.isResumeImplMethodName
import org.jetbrains.kotlin.codegen.inline.coroutines.CoroutineTransformer
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable
@@ -27,6 +26,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.*
import java.util.*
@@ -272,7 +272,7 @@ class AnonymousObjectTransformer(
// Since $$forInline functions are not generated if retransformation is the last one (i.e. call site is not inline)
// link to the function in OUTERCLASS field becomes invalid. However, since $$forInline function always has no-inline
// companion without the suffix, use it.
visitor.visitOuterClass(info.ownerClassName, info.functionName?.removeSuffix(FOR_INLINE_SUFFIX), info.functionDesc)
visitor.visitOuterClass(info.ownerClassName, info.method.name.removeSuffix(FOR_INLINE_SUFFIX), info.method.descriptor)
}
private fun inlineMethodAndUpdateGlobalResult(
@@ -295,7 +295,6 @@ class AnonymousObjectTransformer(
capturedBuilder: ParametersBuilder,
isConstructor: Boolean
): InlineResult {
val typeParametersToReify = inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode)
val parameters =
if (isConstructor) capturedBuilder.buildParameters() else getMethodParametersWithCaptured(capturedBuilder, sourceNode)
@@ -304,7 +303,10 @@ class AnonymousObjectTransformer(
transformationInfo.capturedLambdasToInline, parentRemapper, isConstructor
)
val inliner = MethodInliner(
val reifiedTypeParametersUsages = if (inliningContext.shouldReifyTypeParametersInObjects)
inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode)
else null
val result = MethodInliner(
sourceNode,
parameters,
inliningContext.subInline(transformationInfo.nameGenerator),
@@ -314,26 +316,17 @@ class AnonymousObjectTransformer(
SourceMapCopier(sourceMapper, sourceMap),
InlineCallSiteInfo(
transformationInfo.oldClassName,
sourceNode.name,
if (isConstructor) transformationInfo.newConstructorDescriptor else sourceNode.desc,
Method(sourceNode.name, if (isConstructor) transformationInfo.newConstructorDescriptor else sourceNode.desc),
inliningContext.callSiteInfo.isInlineOrInsideInline,
isSuspendFunctionOrLambda(sourceNode),
inliningContext.root.sourceCompilerForInline.inlineCallSiteInfo.lineNumber
inliningContext.callSiteInfo.file,
inliningContext.callSiteInfo.lineNumber
), null
)
val result = inliner.doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf())
result.reifiedTypeParametersUsages.mergeAll(typeParametersToReify)
).doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf())
reifiedTypeParametersUsages?.let(result.reifiedTypeParametersUsages::mergeAll)
deferringVisitor.visitMaxs(-1, -1)
return result
}
private fun isSuspendFunctionOrLambda(sourceNode: MethodNode): Boolean =
(sourceNode.desc.endsWith(";Lkotlin/coroutines/Continuation;)Ljava/lang/Object;") ||
sourceNode.desc.endsWith(";Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;")) &&
(CoroutineTransformer.findFakeContinuationConstructorClassName(sourceNode) != null ||
languageVersionSettings.isResumeImplMethodName(sourceNode.name.removeSuffix(FOR_INLINE_SUFFIX)))
private fun generateConstructorAndFields(
classBuilder: ClassBuilder,
allCapturedBuilder: ParametersBuilder,
@@ -428,11 +421,13 @@ class AnonymousObjectTransformer(
}
private fun getMethodParametersWithCaptured(capturedBuilder: ParametersBuilder, sourceNode: MethodNode): Parameters {
val builder = ParametersBuilder.initializeBuilderFrom(
oldObjectType,
sourceNode.desc,
isStatic = sourceNode.access and Opcodes.ACC_STATIC != 0
)
val builder = ParametersBuilder.newBuilder()
if (sourceNode.access and Opcodes.ACC_STATIC == 0) {
builder.addThis(oldObjectType, skipped = false)
}
for (type in Type.getArgumentTypes(sourceNode.desc)) {
builder.addNextParameter(type, false)
}
for (param in capturedBuilder.listCaptured()) {
builder.addCapturedParamCopy(param)
}

View File

@@ -23,7 +23,7 @@ import org.jetbrains.org.objectweb.asm.commons.Method
data class MethodId(val ownerInternalName: String, val method: Method)
class InlineCache {
val classBytes: SLRUMap<ClassId, ByteArray> = SLRUMap(30, 20)
val classBytes: SLRUMap<String, ByteArray> = SLRUMap(30, 20)
val methodNodeById: SLRUMap<MethodId, SMAPAndMethodNode> = SLRUMap(60, 50)
}

View File

@@ -1,15 +0,0 @@
/*
* Copyright 2010-2019 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
class InlineCallSiteInfo(
val ownerClassName: String,
val functionName: String?,
val functionDesc: String?,
val isInlineOrInsideInline: Boolean,
val isSuspend: Boolean,
val lineNumber: Int
)

View File

@@ -6,213 +6,94 @@
package org.jetbrains.kotlin.codegen.inline
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
import org.jetbrains.kotlin.codegen.context.ClosureContext
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.Position
import org.jetbrains.kotlin.incremental.components.ScopeKind
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral
import org.jetbrains.kotlin.types.expressions.LabelResolver
import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.org.objectweb.asm.Label
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.commons.Method
import org.jetbrains.org.objectweb.asm.tree.*
import kotlin.math.max
abstract class InlineCodegen<out T : BaseExpressionCodegen>(
protected val codegen: T,
protected val state: GenerationState,
protected val functionDescriptor: FunctionDescriptor,
protected val methodOwner: Type,
protected val jvmSignature: JvmMethodSignature,
private val typeParameterMappings: TypeParameterMappings<*>,
protected val sourceCompiler: SourceCompilerForInline,
private val reifiedTypeInliner: ReifiedTypeInliner<*>
) {
init {
assert(InlineUtil.isInline(functionDescriptor)) {
"InlineCodegen can inline only inline functions: $functionDescriptor"
}
}
// TODO: implement AS_FUNCTION inline strategy
private val asFunctionInline = false
private val initialFrameSize = codegen.frameMap.currentSize
private val isSameModule: Boolean
protected val invocationParamBuilder = ParametersBuilder.newBuilder()
protected val expressionMap = linkedMapOf<Int, FunctionalArgument>()
var activeLambda: LambdaInfo? = null
protected set
private val sourceMapper = sourceCompiler.lazySourceMapper
protected var delayedHiddenWriting: Function0<Unit>? = null
protected val maskValues = ArrayList<Int>()
protected var maskStartIndex = -1
protected var methodHandleInDefaultMethodIndex = -1
init {
isSameModule = sourceCompiler.isCallInsideSameModuleAsDeclared(functionDescriptor)
if (functionDescriptor !is FictitiousArrayConstructor) {
//track changes for property accessor and @JvmName inline functions/property accessors
if (jvmSignature.asmMethod.name != functionDescriptor.name.asString()) {
trackLookup(functionDescriptor)
}
}
}
protected fun throwCompilationException(
nodeAndSmap: SMAPAndMethodNode?, e: Exception, generateNodeText: Boolean
): CompilationException {
val contextDescriptor = sourceCompiler.compilationContextDescriptor
val element = DescriptorToSourceUtils.descriptorToDeclaration(contextDescriptor)
val node = nodeAndSmap?.node
throw CompilationException(
"Couldn't inline method call '" + functionDescriptor.name + "' into\n" +
DescriptorRenderer.DEBUG_TEXT.render(contextDescriptor) + "\n" +
(element?.text ?: "<no source>") +
if (generateNodeText) "\nCause: " + node.nodeText else "",
e, sourceCompiler.callElement as? PsiElement
)
}
private val maskValues = ArrayList<Int>()
private var maskStartIndex = -1
private var methodHandleInDefaultMethodIndex = -1
protected fun generateStub(text: String, codegen: BaseExpressionCodegen) {
leaveTemps()
AsmUtil.genThrow(codegen.v, "java/lang/UnsupportedOperationException", "Call is part of inline cycle: $text")
AsmUtil.genThrow(codegen.visitor, "java/lang/UnsupportedOperationException", "Call is part of inline cycle: $text")
}
protected fun endCall(result: InlineResult, registerLineNumberAfterwards: Boolean) {
leaveTemps()
codegen.propagateChildReifiedTypeParametersUsages(result.reifiedTypeParametersUsages)
state.factory.removeClasses(result.calcClassesToRemove())
codegen.markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards)
}
fun performInline(
typeArguments: List<TypeParameterMarker>?,
inlineDefaultLambdas: Boolean,
mapDefaultSignature: Boolean,
typeSystem: TypeSystemCommonBackendContext,
registerLineNumberAfterwards: Boolean,
) {
fun performInline(registerLineNumberAfterwards: Boolean, isInlineOnly: Boolean) {
var nodeAndSmap: SMAPAndMethodNode? = null
try {
nodeAndSmap = createInlineMethodNode(mapDefaultSignature, typeArguments, typeSystem)
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas), registerLineNumberAfterwards)
nodeAndSmap = sourceCompiler.compileInlineFunction(jvmSignature).apply {
node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
}
val result = inlineCall(nodeAndSmap, isInlineOnly)
leaveTemps()
codegen.propagateChildReifiedTypeParametersUsages(result.reifiedTypeParametersUsages)
codegen.markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards)
state.factory.removeClasses(result.calcClassesToRemove())
} catch (e: CompilationException) {
throw e
} catch (e: InlineException) {
throw throwCompilationException(nodeAndSmap, e, false)
throw CompilationException(
"Couldn't inline method call: ${sourceCompiler.callElementText}",
e, sourceCompiler.callElement as? PsiElement
)
} catch (e: Exception) {
throw throwCompilationException(nodeAndSmap, e, true)
throw CompilationException(
"Couldn't inline method call: ${sourceCompiler.callElementText}\nMethod: ${nodeAndSmap?.node?.nodeText}",
e, sourceCompiler.callElement as? PsiElement
)
}
}
private fun canSkipStackSpillingOnInline(methodNode: MethodNode): Boolean {
// Stack spilling before inline function 'f' call is required if:
// - 'f' is a suspend function
// - 'f' has try-catch blocks
// - 'f' has loops
//
// Instead of checking for loops precisely, we just check if there are any backward jumps -
// that is, a jump from instruction #i to instruction #j where j < i
if (functionDescriptor.isSuspend) return false
if (methodNode.tryCatchBlocks.isNotEmpty()) return false
fun isBackwardJump(fromIndex: Int, toLabel: LabelNode) =
methodNode.instructions.indexOf(toLabel) < fromIndex
val insns = methodNode.instructions.toArray()
for (i in insns.indices) {
val insn = insns[i]
when (insn) {
is JumpInsnNode ->
if (isBackwardJump(i, insn.label)) return false
is LookupSwitchInsnNode -> {
insn.dflt?.let {
if (isBackwardJump(i, it)) return false
}
if (insn.labels.any { isBackwardJump(i, it) }) return false
}
is TableSwitchInsnNode -> {
insn.dflt?.let {
if (isBackwardJump(i, it)) return false
}
if (insn.labels.any { isBackwardJump(i, it) }) return false
}
}
}
return true
}
private fun continuationValue(): StackValue {
assert(codegen is ExpressionCodegen) { "Expected ExpressionCodegen in coroutineContext inlining" }
codegen as ExpressionCodegen
val parentContext = codegen.context.parentContext
return if (parentContext is ClosureContext) {
val originalSuspendLambdaDescriptor =
parentContext.originalSuspendLambdaDescriptor ?: error("No original lambda descriptor found")
codegen.genCoroutineInstanceForSuspendLambda(originalSuspendLambdaDescriptor)
?: error("No stack value for coroutine instance of lambda found")
} else
codegen.getContinuationParameterFromEnclosingSuspendFunctionDescriptor(codegen.context.functionDescriptor)
?: error("No stack value for continuation parameter of suspend function")
}
private fun inlineCall(nodeAndSmap: SMAPAndMethodNode, inlineDefaultLambda: Boolean): InlineResult {
assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" }
private fun inlineCall(nodeAndSmap: SMAPAndMethodNode, isInlineOnly: Boolean): InlineResult {
val node = nodeAndSmap.node
if (inlineDefaultLambda) {
for (lambda in extractDefaultLambdas(node)) {
invocationParamBuilder.buildParameters().getParameterByDeclarationSlot(lambda.offset).functionalArgument = lambda
val prev = expressionMap.put(lambda.offset, lambda)
assert(prev == null) { "Lambda with offset ${lambda.offset} already exists: $prev" }
if (maskStartIndex != -1) {
val parameters = invocationParamBuilder.buildParameters()
val infos = expandMaskConditionsAndUpdateVariableNodes(
node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex,
parameters.parameters.filter { it.functionalArgument === DefaultValueOfInlineParameter }
.mapTo(mutableSetOf()) { parameters.getDeclarationSlot(it) }
)
for (info in infos) {
val lambda = DefaultLambda(info, sourceCompiler)
parameters.getParameterByDeclarationSlot(info.offset).functionalArgument = lambda
val prev = expressionMap.put(info.offset, lambda)
assert(prev == null) { "Lambda with offset ${info.offset} already exists: $prev" }
if (info.needReification) {
lambda.reifiedTypeParametersUsages.mergeAll(reifiedTypeInliner.reifyInstructions(lambda.node.node))
}
for (captured in lambda.capturedVars) {
val param = invocationParamBuilder.addCapturedParam(captured, captured.fieldName, false)
param.remapValue = StackValue.local(codegen.frameMap.enterTemp(param.type), param.type)
param.isSynthetic = true
}
}
}
val reificationResult = reifiedTypeInliner.reifyInstructions(node)
generateClosuresBodies()
//through generation captured parameters will be added to invocationParamBuilder
putClosureParametersOnStack()
val reificationResult = reifiedTypeInliner.reifyInstructions(node)
val parameters = invocationParamBuilder.buildParameters()
@@ -221,13 +102,14 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
sourceCompiler, sourceCompiler.inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings
)
val sourceMapper = sourceCompiler.sourceMapper
val sourceInfo = sourceMapper.sourceInfo!!
val callSite = SourcePosition(codegen.lastLineNumber, sourceInfo.sourceFileName!!, sourceInfo.pathOrCleanFQN)
val inliner = MethodInliner(
node, parameters, info, FieldRemapper(null, null, parameters), isSameModule,
node, parameters, info, FieldRemapper(null, null, parameters), sourceCompiler.isCallInsideSameModuleAsCallee,
"Method inlining " + sourceCompiler.callElementText,
SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP, callSite),
info.callSiteInfo, if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null,
info.callSiteInfo, if (isInlineOnly) InlineOnlySmapSkipper(codegen) else null,
!isInlinedToInlineFunInKotlinRuntime()
) //with captured
@@ -242,43 +124,37 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
val infos = MethodInliner.processReturns(adapter, sourceCompiler.getContextLabels(), null)
generateAndInsertFinallyBlocks(
adapter, infos, (remapper.remap(parameters.argsSizeOnStack + 1).value as StackValue.Local).index
adapter, infos, (remapper.remap(parameters.argsSizeOnStack).value as StackValue.Local).index
)
if (!sourceCompiler.isFinallyMarkerRequired()) {
if (!sourceCompiler.isFinallyMarkerRequired) {
removeFinallyMarkers(adapter)
}
// In case `codegen.v` is `<clinit>`, initializer for the `$assertionsDisabled` field
// In case `codegen.visitor` is `<clinit>`, initializer for the `$assertionsDisabled` field
// needs to be inserted before the code that actually uses it.
generateAssertFieldIfNeeded(info)
val shouldSpillStack = !canSkipStackSpillingOnInline(node)
if (shouldSpillStack) {
addInlineMarker(codegen.v, true)
if (info.generateAssertField) {
generateAssertField()
}
adapter.accept(MethodBodyVisitor(codegen.v))
val shouldSpillStack = node.requiresEmptyStackOnEntry()
if (shouldSpillStack) {
addInlineMarker(codegen.v, false)
addInlineMarker(codegen.visitor, true)
}
adapter.accept(MethodBodyVisitor(codegen.visitor))
if (shouldSpillStack) {
addInlineMarker(codegen.visitor, false)
}
return result
}
abstract fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda>
abstract fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean
fun generateAndInsertFinallyBlocks(
private fun generateAndInsertFinallyBlocks(
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
offsetForFinallyLocalVar: Int
) {
if (!sourceCompiler.hasFinallyBlocks()) return
val extensionPoints = HashMap<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks>()
for (insertPoint in insertPoints) {
extensionPoints.put(insertPoint.beforeIns, insertPoint)
}
val extensionPoints = insertPoints.associateBy { it.beforeIns }
val processor = DefaultProcessor(intoNode, offsetForFinallyLocalVar)
var curFinallyDepth = 0
@@ -292,47 +168,35 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
val extension = extensionPoints[curInstr]
if (extension != null) {
val start = Label()
var nextFreeLocalIndex = processor.nextFreeLocalIndex
for (local in processor.localVarsMetaInfo.currentIntervals) {
val size = Type.getType(local.node.desc).size
nextFreeLocalIndex = max(offsetForFinallyLocalVar + local.node.index + size, nextFreeLocalIndex)
}
val start = Label()
val finallyNode = createEmptyMethodNode()
finallyNode.visitLabel(start)
val finallyCodegen =
sourceCompiler.createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode, curFinallyDepth)
val frameMap = finallyCodegen.frameMap
val mark = frameMap.mark()
var marker = -1
val intervals = processor.localVarsMetaInfo.currentIntervals
for (interval in intervals) {
marker = max(interval.node.index + 1, marker)
}
while (frameMap.currentSize < max(processor.nextFreeLocalIndex, offsetForFinallyLocalVar + marker)) {
frameMap.enterTemp(Type.INT_TYPE)
}
sourceCompiler.generateFinallyBlocksIfNeeded(
finallyCodegen, extension.returnType, extension.finallyIntervalEnd.label, extension.jumpTarget
val mark = codegen.frameMap.skipTo(nextFreeLocalIndex)
sourceCompiler.generateFinallyBlocks(
finallyNode, curFinallyDepth, extension.returnType, extension.finallyIntervalEnd.label, extension.jumpTarget
)
//Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method
mark.dropTo()
insertNodeBefore(finallyNode, intoNode, curInstr)
val splitBy = SimpleInterval(start.info as LabelNode, extension.finallyIntervalEnd)
processor.tryBlocksMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true)
processor.localVarsMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true);
mark.dropTo()
processor.localVarsMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true)
}
curInstr = curInstr.next
}
processor.substituteTryBlockNodes(intoNode)
processor.substituteLocalVarTable(intoNode);
processor.substituteLocalVarTable(intoNode)
}
protected abstract fun generateAssertFieldIfNeeded(info: RootInliningContext)
protected abstract fun generateAssertField()
private fun isInlinedToInlineFunInKotlinRuntime(): Boolean {
val codegen = this.codegen as? ExpressionCodegen ?: return false
@@ -345,90 +209,52 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
}
}
private fun generateClosuresBodies() {
for (info in expressionMap.values) {
if (info is LambdaInfo) {
info.generateLambdaBody(sourceCompiler, reifiedTypeInliner)
}
protected fun rememberClosure(parameterType: Type, index: Int, lambdaInfo: LambdaInfo) {
val closureInfo = invocationParamBuilder.addNextValueParameter(parameterType, true, null, index)
closureInfo.functionalArgument = lambdaInfo
expressionMap[closureInfo.index] = lambdaInfo
}
protected fun putCapturedToLocalVal(stackValue: StackValue, capturedParam: CapturedParamDesc, kotlinType: KotlinType?) {
val info = invocationParamBuilder.addCapturedParam(capturedParam, capturedParam.fieldName, false)
if (stackValue.isLocalWithNoBoxing(JvmKotlinType(info.type, kotlinType))) {
info.remapValue = stackValue
} else {
stackValue.put(info.type, kotlinType, codegen.visitor)
val local = StackValue.local(codegen.frameMap.enterTemp(info.type), info.type)
local.store(StackValue.onStack(info.type), codegen.visitor)
info.remapValue = local
info.isSynthetic = true
}
}
protected fun putArgumentOrCapturedToLocalVal(
jvmKotlinType: JvmKotlinType,
stackValue: StackValue,
capturedParamIndex: Int,
parameterIndex: Int,
kind: ValueKind
) {
val isDefaultParameter = kind === ValueKind.DEFAULT_PARAMETER
val jvmType = jvmKotlinType.type
val kotlinType = jvmKotlinType.kotlinType
if (!isDefaultParameter && shouldPutGeneralValue(jvmType, kotlinType, stackValue)) {
stackValue.put(jvmType, kotlinType, codegen.v)
protected fun putArgumentToLocalVal(jvmKotlinType: JvmKotlinType, stackValue: StackValue, parameterIndex: Int, kind: ValueKind) {
if (kind === ValueKind.DEFAULT_MASK || kind === ValueKind.METHOD_HANDLE_IN_DEFAULT) {
return processDefaultMaskOrMethodHandler(stackValue, kind)
}
if (!asFunctionInline && Type.VOID_TYPE !== jvmType) {
//TODO remap only inlinable closure => otherwise we could get a lot of problem
val couldBeRemapped = !shouldPutGeneralValue(jvmType, kotlinType, stackValue) && kind !== ValueKind.DEFAULT_PARAMETER
val remappedValue = if (couldBeRemapped) stackValue else null
val info: ParameterInfo
if (capturedParamIndex >= 0) {
val capturedParamInfoInLambda = activeLambda!!.capturedVars[capturedParamIndex]
info = invocationParamBuilder.addCapturedParam(capturedParamInfoInLambda, capturedParamInfoInLambda.fieldName, false)
info.remapValue = remappedValue
} else {
info = invocationParamBuilder.addNextValueParameter(jvmType, false, remappedValue, parameterIndex)
info.functionalArgument = when (kind) {
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND ->
NonInlineableArgumentForInlineableParameterCalledInSuspend
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER -> NonInlineableArgumentForInlineableSuspendParameter
else -> null
}
}
recordParameterValueInLocalVal(
false,
isDefaultParameter || kind === ValueKind.DEFAULT_LAMBDA_CAPTURED_PARAMETER,
info
)
val info = invocationParamBuilder.addNextValueParameter(jvmKotlinType.type, false, null, parameterIndex)
info.functionalArgument = when (kind) {
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND ->
NonInlineableArgumentForInlineableParameterCalledInSuspend
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER ->
NonInlineableArgumentForInlineableSuspendParameter
ValueKind.DEFAULT_INLINE_PARAMETER ->
DefaultValueOfInlineParameter
else -> null
}
}
protected fun recordParameterValueInLocalVal(
delayedWritingToLocals: Boolean,
skipStore: Boolean,
vararg infos: ParameterInfo
): Function0<Unit>? {
val index = IntArray(infos.size) { i ->
if (!infos[i].isSkippedOrRemapped) {
codegen.frameMap.enterTemp(infos[i].type)
} else -1
}
val possibleLazyTask = {
for (i in infos.indices.reversed()) {
val info = infos[i]
if (!info.isSkippedOrRemapped) {
val type = info.type
val local = StackValue.local(index[i], type)
if (!skipStore) {
local.store(StackValue.onStack(info.typeOnStack), codegen.v)
}
if (info is CapturedParamInfo) {
info.remapValue = local
info.isSynthetic = true
}
}
when {
kind === ValueKind.DEFAULT_PARAMETER || kind === ValueKind.DEFAULT_INLINE_PARAMETER ->
codegen.frameMap.enterTemp(info.type) // the inline function will put the value into this slot
stackValue.isLocalWithNoBoxing(jvmKotlinType) ->
info.remapValue = stackValue
else -> {
stackValue.put(info.type, jvmKotlinType.kotlinType, codegen.visitor)
codegen.visitor.store(codegen.frameMap.enterTemp(info.type), info.type)
}
}
if (delayedWritingToLocals) return possibleLazyTask
possibleLazyTask()
return null
}
private fun leaveTemps() {
invocationParamBuilder.listAllParams().asReversed().forEach { param ->
if (!param.isSkippedOrRemapped || CapturedParamInfo.isSynthetic(param)) {
@@ -437,45 +263,11 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
}
}
private fun putClosureParametersOnStack() {
for (next in expressionMap.values) {
//closure parameters for bounded callable references are generated inplace
if (next is LambdaInfo) {
if (next is ExpressionLambda && next.isBoundCallableReference) continue
putClosureParametersOnStack(next, null)
}
}
}
abstract protected fun putClosureParametersOnStack(next: LambdaInfo, functionReferenceReceiver: StackValue?)
protected fun rememberCapturedForDefaultLambda(defaultLambda: DefaultLambda) {
for ((paramIndex, captured) in defaultLambda.capturedVars.withIndex()) {
putArgumentOrCapturedToLocalVal(
JvmKotlinType(captured.type),
//HACK: actually parameter would be placed on stack in default function
// also see ValueKind.DEFAULT_LAMBDA_CAPTURED_PARAMETER check
StackValue.onStack(captured.type),
paramIndex,
paramIndex,
ValueKind.DEFAULT_LAMBDA_CAPTURED_PARAMETER
)
defaultLambda.parameterOffsetsInDefault.add(invocationParamBuilder.nextParameterOffset)
}
}
protected fun processDefaultMaskOrMethodHandler(value: StackValue, kind: ValueKind): Boolean {
if (kind !== ValueKind.DEFAULT_MASK && kind !== ValueKind.METHOD_HANDLE_IN_DEFAULT) {
return false
}
assert(value is StackValue.Constant) {
"Additional default method argument should be constant, but " + value
}
private fun processDefaultMaskOrMethodHandler(value: StackValue, kind: ValueKind) {
assert(value is StackValue.Constant) { "Additional default method argument should be constant, but $value" }
val constantValue = (value as StackValue.Constant).value
if (kind === ValueKind.DEFAULT_MASK) {
assert(constantValue is Int) { "Mask should be of Integer type, but " + constantValue }
assert(constantValue is Int) { "Mask should be of Integer type, but $constantValue" }
maskValues.add(constantValue as Int)
if (maskStartIndex == -1) {
maskStartIndex = invocationParamBuilder.listAllParams().sumOf {
@@ -486,228 +278,40 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
assert(constantValue == null) { "Additional method handle for default argument should be null, but " + constantValue!! }
methodHandleInDefaultMethodIndex = maskStartIndex + maskValues.size
}
return true
}
private fun trackLookup(functionOrAccessor: FunctionDescriptor) {
val functionOrAccessorName = jvmSignature.asmMethod.name
val lookupTracker = state.configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER) ?: return
val location = sourceCompiler.lookupLocation.location ?: return
val position = if (lookupTracker.requiresPosition) location.position else Position.NO_POSITION
val classOrPackageFragment = functionOrAccessor.containingDeclaration
lookupTracker.record(
location.filePath,
position,
DescriptorUtils.getFqName(classOrPackageFragment).asString(),
ScopeKind.CLASSIFIER,
functionOrAccessorName
)
}
internal fun createInlineMethodNode(
callDefault: Boolean,
typeArguments: List<TypeParameterMarker>?,
typeSystem: TypeSystemCommonBackendContext
): SMAPAndMethodNode {
val intrinsic = generateInlineIntrinsic(state, functionDescriptor, typeArguments, typeSystem)
if (intrinsic != null) {
return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
}
var asmMethod = mapMethod(callDefault)
if (asmMethod.name.contains("-") &&
!state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME) &&
classFileContainsMethod(functionDescriptor, state, asmMethod) == false
) {
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = true
asmMethod = mapMethod(callDefault)
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = false
}
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
if (!isBuiltInArrayIntrinsic(functionDescriptor) && !descriptorIsDeserialized(directMember)) {
val node = sourceCompiler.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod)
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
return node
}
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature)
}
private fun mapMethod(callDefault: Boolean): Method =
if (callDefault) state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompiler.contextKind)
else mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
companion object {
private fun StackValue.isLocalWithNoBoxing(expected: JvmKotlinType): Boolean =
isPrimitive(expected.type) == isPrimitive(type) &&
!StackValue.requiresInlineClassBoxingOrUnboxing(type, kotlinType, expected.type, expected.kotlinType) &&
(this is StackValue.Local || isCapturedInlineParameter())
internal fun createSpecialInlineMethodNodeFromBinaries(functionDescriptor: FunctionDescriptor, state: GenerationState): MethodNode {
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
assert(directMember is DescriptorWithContainerSource) {
"Function is not in binaries: $functionDescriptor"
}
assert(directMember is FunctionDescriptor && directMember.isOperator) {
"Operator function expected: $directMember"
}
val methodOwner = state.typeMapper.mapImplementationOwner(functionDescriptor)
val jvmSignature = state.typeMapper.mapSignatureWithGeneric(functionDescriptor, OwnerKind.IMPLEMENTATION)
val asmMethod = mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature).node
private fun StackValue.isCapturedInlineParameter(): Boolean {
val field = if (this is StackValue.FieldForSharedVar) receiver else this
return field is StackValue.Field && field.descriptor is ParameterDescriptor &&
InlineUtil.isInlineParameter(field.descriptor) &&
InlineUtil.isInline(field.descriptor.containingDeclaration)
}
private fun getCompiledMethodNodeInner(
functionDescriptor: FunctionDescriptor,
directMember: CallableMemberDescriptor,
asmMethod: Method,
methodOwner: Type,
state: GenerationState,
jvmSignature: JvmMethodSignature
): SMAPAndMethodNode {
val methodId = MethodId(methodOwner.internalName, asmMethod)
// Stack spilling before inline function call is required if the inlined bytecode has:
// 1. try-catch blocks - otherwise the stack spilling before and after them will not be correct;
// 2. suspension points - again, the stack spilling around them is otherwise wrong;
// 3. loops - OpenJDK cannot JIT-optimize between loop iterations if the stack is not empty.
// Instead of checking for loops precisely, we just check if there are any backward jumps -
// that is, a jump from instruction #i to instruction #j where j < i.
private fun MethodNode.requiresEmptyStackOnEntry(): Boolean = tryCatchBlocks.isNotEmpty() ||
instructions.toArray().any { isBeforeSuspendMarker(it) || isBeforeInlineSuspendMarker(it) || isBackwardsJump(it) }
val resultInCache = state.inlineCache.methodNodeById.getOrPut(methodId) {
val result = doCreateMethodNodeFromCompiled(directMember, state, asmMethod)
?: if (functionDescriptor.isSuspend)
doCreateMethodNodeFromCompiled(directMember, state, jvmSignature.asmMethod)
else
null
result ?:
throw IllegalStateException("Couldn't obtain compiled function body for $functionDescriptor")
}
return SMAPAndMethodNode(cloneMethodNode(resultInCache.node), resultInCache.classSMAP)
private fun MethodNode.isBackwardsJump(insn: AbstractInsnNode): Boolean = when (insn) {
is JumpInsnNode -> isBackwardsJump(insn, insn.label)
is LookupSwitchInsnNode ->
insn.dflt?.let { to -> isBackwardsJump(insn, to) } == true || insn.labels.any { to -> isBackwardsJump(insn, to) }
is TableSwitchInsnNode ->
insn.dflt?.let { to -> isBackwardsJump(insn, to) } == true || insn.labels.any { to -> isBackwardsJump(insn, to) }
else -> false
}
private fun createDefaultFakeSMAP() = SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
// For suspend inline functions we generate two methods:
// 1) normal one: with state machine to call directly
// 2) for inliner: with mangled name and without state machine
private fun mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor: FunctionDescriptor, asmMethod: Method): Method {
if (!functionDescriptor.isSuspend) return asmMethod
return Method("${asmMethod.name}$FOR_INLINE_SUFFIX", asmMethod.descriptor)
}
private fun getDirectMemberAndCallableFromObject(functionDescriptor: FunctionDescriptor): CallableMemberDescriptor {
val directMember = JvmCodegenUtil.getDirectMember(functionDescriptor)
return (directMember as? ImportedFromObjectCallableDescriptor<*>)?.callableFromObject ?: directMember
}
private fun doCreateMethodNodeFromCompiled(
callableDescriptor: CallableMemberDescriptor,
state: GenerationState,
asmMethod: Method
): SMAPAndMethodNode? {
if (isBuiltInArrayIntrinsic(callableDescriptor)) {
val body = when {
callableDescriptor is FictitiousArrayConstructor -> IntrinsicArrayConstructors.generateArrayConstructorBody(asmMethod)
callableDescriptor.name.asString() == "emptyArray" -> IntrinsicArrayConstructors.generateEmptyArrayBody(asmMethod)
callableDescriptor.name.asString() == "arrayOf" -> IntrinsicArrayConstructors.generateArrayOfBody(asmMethod)
else -> throw UnsupportedOperationException("Not an array intrinsic: $callableDescriptor")
}
return SMAPAndMethodNode(body, SMAP(listOf()))
}
assert(callableDescriptor is DescriptorWithContainerSource) { "Not a deserialized function or proper: $callableDescriptor" }
val containingClasses =
KotlinTypeMapper.getContainingClassesForDeserializedCallable(callableDescriptor as DescriptorWithContainerSource)
val containerId = containingClasses.implClassId
val bytes = state.inlineCache.classBytes.getOrPut(containerId) {
findVirtualFile(state, containerId)?.contentsToByteArray()
?: throw IllegalStateException("Couldn't find declaration file for $containerId")
}
val classType = AsmUtil.asmTypeByClassId(containerId)
val methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, classType)
if (methodNode == null && requiresFunctionNameManglingForReturnType(callableDescriptor)) {
val nameWithoutManglingSuffix = asmMethod.name.stripManglingSuffixOrNull()
if (nameWithoutManglingSuffix != null) {
val methodWithoutMangling = getMethodNode(bytes, nameWithoutManglingSuffix, asmMethod.descriptor, classType)
if (methodWithoutMangling != null) return methodWithoutMangling
}
return getMethodNode(bytes, "$nameWithoutManglingSuffix-impl", asmMethod.descriptor, classType)
}
return methodNode
}
private fun String.stripManglingSuffixOrNull(): String? {
val dashIndex = indexOf('-')
return if (dashIndex < 0) null else substring(0, dashIndex)
}
private fun isBuiltInArrayIntrinsic(callableDescriptor: CallableMemberDescriptor): Boolean {
if (callableDescriptor is FictitiousArrayConstructor) return true
val name = callableDescriptor.name.asString()
return (name == "arrayOf" || name == "emptyArray") && callableDescriptor.containingDeclaration.let { container ->
container is PackageFragmentDescriptor && container.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME
}
}
/*descriptor is null for captured vars*/
private fun shouldPutGeneralValue(type: Type, kotlinType: KotlinType?, stackValue: StackValue): Boolean {
//remap only inline functions (and maybe non primitives)
//TODO - clean assertion and remapping logic
// don't remap boxing/unboxing primitives
if (isPrimitive(type) != isPrimitive(stackValue.type)) {
return true
}
// don't remap boxing/unboxing inline classes
if (StackValue.requiresInlineClassBoxingOrUnboxing(stackValue.type, stackValue.kotlinType, type, kotlinType)) {
return true
}
if (stackValue is StackValue.Local) {
return false
}
var field = stackValue
if (stackValue is StackValue.FieldForSharedVar) {
field = stackValue.receiver
}
//check that value corresponds to captured inlining parameter
if (field is StackValue.Field) {
val varDescriptor = field.descriptor
//check that variable is inline function parameter
return !(varDescriptor is ParameterDescriptor &&
InlineUtil.isInlineParameter(varDescriptor) &&
InlineUtil.isInline(varDescriptor.containingDeclaration))
}
return true
}
fun getDeclarationLabels(lambdaOrFun: PsiElement?, descriptor: DeclarationDescriptor): Set<String> {
val result = HashSet<String>()
if (lambdaOrFun != null) {
val label = LabelResolver.getLabelNameIfAny(lambdaOrFun)
if (label != null) {
result.add(label.asString())
}
}
if (!isFunctionLiteral(descriptor)) {
if (!descriptor.name.isSpecial) {
result.add(descriptor.name.asString())
}
result.add(FIRST_FUN_LABEL)
}
return result
}
private fun MethodNode.isBackwardsJump(from: AbstractInsnNode, to: LabelNode): Boolean =
instructions.indexOf(to) < instructions.indexOf(from)
}
}
val BaseExpressionCodegen.v: InstructionAdapter
get() = visitor

View File

@@ -15,15 +15,13 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class InlineCodegenForDefaultBody(
private val function: FunctionDescriptor,
codegen: ExpressionCodegen,
val state: GenerationState,
private val methodOwner: Type,
private val jvmSignature: JvmMethodSignature,
private val sourceCompilerForInline: SourceCompilerForInline
private val sourceCompilerForInline: PsiSourceCompilerForInline
) : CallGenerator {
private val sourceMapper: SourceMapper = codegen.parentCodegen.orCreateSourceMapper
@@ -39,32 +37,22 @@ class InlineCodegenForDefaultBody(
}
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
val nodeAndSmap = PsiInlineCodegen(
codegen, state, function, methodOwner, jvmSignature, TypeParameterMappings(), sourceCompilerForInline
).createInlineMethodNode(
callDefault, null, codegen.typeSystem
)
val childSourceMapper = SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP)
val node = nodeAndSmap.node
val transformedMethod = MethodNode(
node.access,
node.name,
node.desc,
node.signature,
node.exceptions.toTypedArray()
)
assert(!callDefault) { "inlining default stub into another default stub" }
val (node, smap) = sourceCompilerForInline.compileInlineFunction(jvmSignature)
val childSourceMapper = SourceMapCopier(sourceMapper, smap)
val argsSize =
(Type.getArgumentsAndReturnSizes(jvmSignature.asmMethod.descriptor) ushr 2) - if (callableMethod.isStaticCall()) 1 else 0
node.accept(object : InlineAdapter(transformedMethod, 0, childSourceMapper) {
override fun visitLocalVariable(name: String, desc: String, signature: String?, start: Label, end: Label, index: Int) {
val startLabel = if (index < argsSize) methodStartLabel else start
super.visitLocalVariable(name, desc, signature, startLabel, end, index)
}
})
// `$default` is only for Kotlin use so it has no `$$forInline` version - this *is* what the inliner will use.
node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
node.accept(object : MethodBodyVisitor(codegen.visitor) {
// The LVT was not generated at all, so move the start of parameters to the start of the method.
override fun visitLocalVariable(name: String, desc: String, signature: String?, start: Label, end: Label, index: Int) =
super.visitLocalVariable(name, desc, signature, if (index < argsSize) methodStartLabel else start, end, index)
transformedMethod.accept(MethodBodyVisitor(codegen.visitor))
override fun visitLineNumber(line: Int, start: Label) =
super.visitLineNumber(childSourceMapper.mapLineNumber(line), start)
})
}
override fun genValueAndPut(
@@ -85,7 +73,7 @@ class InlineCodegenForDefaultBody(
throw UnsupportedOperationException("Shouldn't be called")
}
override fun processAndPutHiddenParameters(justProcess: Boolean) {
override fun processHiddenParameters() {
throw UnsupportedOperationException("Shouldn't be called")
}

View File

@@ -44,8 +44,16 @@ open class InliningContext(
val lambdaInfo: LambdaInfo?,
val classRegeneration: Boolean
) {
val isInliningLambda
get() = lambdaInfo != null
val isInliningLambda = lambdaInfo != null
// Consider this arrangement:
// inline fun <reified T> f(x: () -> Unit = { /* uses `T` in a local class */ }) = x()
// inline fun <reified V> g() = f<...> { /* uses `V` in a local class */ }
// When inlining `f` into `g`, we need to reify the contents of the default for `x` (if it was used), but not the
// contents of the lambda passed as the argument in `g` as all reified type parameters used by the latter are not from `f`.
val shouldReifyTypeParametersInObjects: Boolean
get() = lambdaInfo == null || lambdaInfo is DefaultLambda
var generateAssertField = false
@@ -54,7 +62,8 @@ open class InliningContext(
var isContinuation: Boolean = false
val isRoot: Boolean = parent == null
val isRoot: Boolean
get() = parent == null
val root: RootInliningContext
get() = if (isRoot) this as RootInliningContext else parent!!.root

View File

@@ -6,24 +6,18 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.coroutines.isCoroutineSuperClass
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
import kotlin.properties.Delegates
interface FunctionalArgument
abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgument {
abstract val isBoundCallableReference: Boolean
abstract val isSuspend: Boolean
abstract class LambdaInfo : FunctionalArgument {
abstract val lambdaClassType: Type
abstract val invokeMethod: Method
@@ -41,13 +35,17 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
val reifiedTypeParametersUsages = ReifiedTypeParametersUsages()
abstract fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>)
open val hasDispatchReceiver = true
open val hasDispatchReceiver
get() = true
fun addAllParameters(remapper: FieldRemapper): Parameters {
val builder = ParametersBuilder.initializeBuilderFrom(OBJECT_TYPE, invokeMethod.descriptor, this)
val builder = ParametersBuilder.newBuilder()
if (hasDispatchReceiver) {
builder.addThis(lambdaClassType, skipped = true).functionalArgument = this
}
for (type in Type.getArgumentTypes(invokeMethod.descriptor)) {
builder.addNextParameter(type, skipped = false)
}
for (info in capturedVars) {
val field = remapper.findField(FieldInsnNode(0, info.containingLambdaName, info.fieldName, ""))
?: error("Captured field not found: " + info.containingLambdaName + "." + info.fieldName)
@@ -69,76 +67,75 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
object NonInlineableArgumentForInlineableParameterCalledInSuspend : FunctionalArgument
object NonInlineableArgumentForInlineableSuspendParameter : FunctionalArgument
object DefaultValueOfInlineParameter : FunctionalArgument
abstract class ExpressionLambda(isCrossInline: Boolean) : LambdaInfo(isCrossInline) {
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>) {
abstract class ExpressionLambda : LambdaInfo() {
fun generateLambdaBody(sourceCompiler: SourceCompilerForInline) {
node = sourceCompiler.generateLambdaBody(this, reifiedTypeParametersUsages)
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
}
}
abstract class DefaultLambda(
private val capturedArgs: Array<Type>,
isCrossinline: Boolean,
val offset: Int,
val needReification: Boolean
) : LambdaInfo(isCrossinline) {
class DefaultLambda(info: ExtractedDefaultLambda, sourceCompiler: SourceCompilerForInline) : LambdaInfo() {
val isBoundCallableReference: Boolean
final override var isBoundCallableReference by Delegates.notNull<Boolean>()
private set
override val lambdaClassType: Type = info.type
override val capturedVars: List<CapturedParamDesc>
val parameterOffsetsInDefault: MutableList<Int> = arrayListOf()
override val invokeMethod: Method
get() = Method(node.node.name, node.node.desc)
final override lateinit var invokeMethod: Method
private set
private val nullableAnyType = sourceCompiler.state.module.builtIns.nullableAnyType
final override lateinit var capturedVars: List<CapturedParamDesc>
private set
override val invokeMethodParameters: List<KotlinType>
get() = List(invokeMethod.argumentTypes.size) { nullableAnyType }
var originalBoundReceiverType: Type? = null
private set
override val invokeMethodReturnType: KotlinType
get() = nullableAnyType
override val isSuspend = false // TODO: it should probably be true sometimes, but it never was
val originalBoundReceiverType: Type?
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>) {
val classBytes = loadClassBytesByInternalName(sourceCompiler.state, lambdaClassType.internalName)
init {
val classBytes =
sourceCompiler.state.inlineCache.classBytes.getOrPut(lambdaClassType.internalName) {
loadClassBytesByInternalName(sourceCompiler.state, lambdaClassType.internalName)
}
val superName = ClassReader(classBytes).superName
val isPropertyReference = superName in PROPERTY_REFERENCE_SUPER_CLASSES
val isFunctionReference = superName == FUNCTION_REFERENCE.internalName || superName == FUNCTION_REFERENCE_IMPL.internalName
val constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
val constructor = getMethodNode(classBytes, "<init>", constructorDescriptor, lambdaClassType)?.node
assert(constructor != null || capturedArgs.isEmpty()) {
"Can't find non-default constructor <init>$constructorDescriptor for default lambda $lambdaClassType"
// 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)) {
"suspend default lambda ${lambdaClassType.internalName} cannot be inlined; use a function reference instead"
}
val constructorMethod = Method("<init>", Type.VOID_TYPE, info.capturedArgs)
val constructor = getMethodNode(classBytes, lambdaClassType, constructorMethod)?.node
assert(constructor != null || info.capturedArgs.isEmpty()) {
"can't find constructor '$constructorMethod' for default lambda '${lambdaClassType.internalName}'"
}
val isPropertyReference = superName in PROPERTY_REFERENCE_SUPER_CLASSES
val isReference = isPropertyReference ||
superName == FUNCTION_REFERENCE.internalName || superName == FUNCTION_REFERENCE_IMPL.internalName
// This only works for primitives but not inline classes, since information about the Kotlin type of the bound
// receiver is not present anywhere. This is why with JVM_IR the constructor argument of bound references
// is already `Object`, and this field is never used.
originalBoundReceiverType =
info.capturedArgs.singleOrNull()?.takeIf { isReference && AsmUtil.isPrimitive(it) }
capturedVars =
if (isFunctionReference || isPropertyReference)
constructor?.desc?.let { Type.getArgumentTypes(it) }?.singleOrNull()?.let {
originalBoundReceiverType = it
listOf(capturedParamDesc(AsmUtil.RECEIVER_PARAMETER_NAME, AsmUtil.boxType(it), isSuspend = false))
if (isReference)
info.capturedArgs.singleOrNull()?.let {
// See `InlinedLambdaRemapper`
listOf(capturedParamDesc(AsmUtil.RECEIVER_PARAMETER_NAME, OBJECT_TYPE, isSuspend = false))
} ?: emptyList()
else
constructor?.findCapturedFieldAssignmentInstructions()?.map { fieldNode ->
capturedParamDesc(fieldNode.name, Type.getType(fieldNode.desc), isSuspend = false)
}?.toList() ?: emptyList()
isBoundCallableReference = (isFunctionReference || isPropertyReference) && capturedVars.isNotEmpty()
val invokeNameFallback = (if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString()
val invokeMethod = mapAsmMethod(sourceCompiler, isPropertyReference)
// TODO: `signatureAmbiguity = true` ignores the argument types from `invokeDescriptor` and only looks at the count.
// This effectively masks incorrect results from `mapAsmDescriptor`, which hopefully won't manifest in another way.
node = getMethodNode(classBytes, invokeMethod.name, invokeMethod.descriptor, lambdaClassType, signatureAmbiguity = true)
?: getMethodNode(classBytes, invokeNameFallback, invokeMethod.descriptor, lambdaClassType, signatureAmbiguity = true)
?: error("Can't find method '$invokeMethod' in '${lambdaClassType.internalName}'")
this.invokeMethod = Method(node.node.name, node.node.desc)
if (needReification) {
//nested classes could also require reification
reifiedTypeParametersUsages.mergeAll(reifiedTypeInliner.reifyInstructions(node.node))
}
isBoundCallableReference = isReference && capturedVars.isNotEmpty()
node = loadDefaultLambdaBody(classBytes, lambdaClassType, isPropertyReference)
}
protected abstract fun mapAsmMethod(sourceCompiler: SourceCompilerForInline, isPropertyReference: Boolean): Method
private companion object {
val PROPERTY_REFERENCE_SUPER_CLASSES =
listOf(

View File

@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.coroutines.continuationAsmType
import org.jetbrains.kotlin.codegen.inline.FieldRemapper.Companion.foldName
import org.jetbrains.kotlin.codegen.inline.coroutines.CoroutineTransformer
import org.jetbrains.kotlin.codegen.inline.coroutines.isSuspendLambdaCapturedByOuterObjectOrLambda
import org.jetbrains.kotlin.codegen.inline.coroutines.markNoinlineLambdaIfSuspend
import org.jetbrains.kotlin.codegen.inline.coroutines.surroundInvokesWithSuspendMarkersIfNeeded
import org.jetbrains.kotlin.codegen.optimization.ApiVersionCallsPreprocessingMethodTransformer
@@ -18,13 +17,12 @@ import org.jetbrains.kotlin.codegen.optimization.common.ControlFlowGraph
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.fixStack.*
import org.jetbrains.kotlin.codegen.optimization.fixStack.FastStackAnalyzer
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.utils.SmartList
@@ -38,8 +36,6 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.commons.LocalVariablesSorter
import org.jetbrains.org.objectweb.asm.commons.MethodRemapper
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.util.Printer
import java.util.*
@@ -59,8 +55,10 @@ class MethodInliner(
) {
private val languageVersionSettings = inliningContext.state.languageVersionSettings
private val invokeCalls = ArrayList<InvokeCall>()
//keeps order
private val transformations = ArrayList<TransformationInfo>()
//current state
private val currentTypeMapping = HashMap<String, String?>()
private val result = InlineResult.create()
@@ -94,10 +92,6 @@ class MethodInliner(
): InlineResult {
//analyze body
var transformedNode = markPlacesForInlineAndRemoveInlinable(node, returnLabels, finallyDeepShift)
if (inliningContext.isInliningLambda && isDefaultLambdaWithReification(inliningContext.lambdaInfo!!)) {
//TODO maybe move reification in one place
inliningContext.root.inlineMethodReifier.reifyInstructions(transformedNode)
}
//substitute returns with "goto end" instruction to keep non local returns in lambdas
val end = linkedLabel()
@@ -230,11 +224,11 @@ class MethodInliner(
return
}
val nullableAnyType = inliningContext.root.sourceCompilerForInline.compilationContextDescriptor.builtIns.nullableAnyType
val nullableAnyType = inliningContext.state.module.builtIns.nullableAnyType
val expectedParameters = info.invokeMethod.argumentTypes
val expectedKotlinParameters = info.invokeMethodParameters
val argumentCount = Type.getArgumentTypes(desc).size.let {
if (!inliningContext.root.state.isIrBackend && info.isSuspend && it < expectedParameters.size) {
if (info is PsiExpressionLambda && info.invokeMethodDescriptor.isSuspend && it < expectedParameters.size) {
// Inlining suspend lambda into a function that takes a non-suspend lambda.
// In the IR backend, this cannot happen as inline lambdas are not lowered.
addFakeContinuationMarker(this)
@@ -279,7 +273,8 @@ class MethodInliner(
val varRemapper = LocalVarRemapper(lambdaParameters, valueParamShift)
//TODO add skipped this and receiver
val lambdaResult = inliner.doInline(localVariablesSorter, varRemapper, true, info.returnLabels, invokeCall.finallyDepthShift)
val lambdaResult =
inliner.doInline(localVariablesSorter, varRemapper, true, info.returnLabels, invokeCall.finallyDepthShift)
result.mergeWithNotChangeInfo(lambdaResult)
result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages)
result.reifiedTypeParametersUsages.mergeAll(info.reifiedTypeParametersUsages)
@@ -309,7 +304,7 @@ class MethodInliner(
} else capturedParamDesc
visitFieldInsn(
Opcodes.GETSTATIC, realDesc.containingLambdaName,
FieldRemapper.foldName(realDesc.fieldName), realDesc.type.descriptor
foldName(realDesc.fieldName), realDesc.type.descriptor
)
}
super.visitMethodInsn(opcode, info.newClassName, name, info.newConstructorDescriptor, itf)
@@ -323,10 +318,11 @@ class MethodInliner(
} else {
super.visitMethodInsn(opcode, owner, name, desc, itf)
}
} else if ((!inliningContext.isInliningLambda || isDefaultLambdaWithReification(inliningContext.lambdaInfo!!)) &&
ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))
) {
//we shouldn't process here content of inlining lambda it should be reified at external level except default lambdas
} else if (ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))) {
// If objects are reified, the marker will be recreated by `handleAnonymousObjectRegeneration` above.
if (!inliningContext.shouldReifyTypeParametersInObjects) {
super.visitMethodInsn(opcode, owner, name, desc, itf)
}
} else {
super.visitMethodInsn(opcode, owner, name, desc, itf)
}
@@ -351,9 +347,6 @@ class MethodInliner(
return resultNode
}
private fun isDefaultLambdaWithReification(lambdaInfo: LambdaInfo) =
lambdaInfo is DefaultLambda && lambdaInfo.needReification
private fun prepareNode(node: MethodNode, finallyDeepShift: Int): MethodNode {
node.instructions.resetLabels()
@@ -383,10 +376,7 @@ class MethodInliner(
private fun getNewIndex(`var`: Int): Int {
val lambdaInfo = inliningContext.lambdaInfo
if (reorderIrLambdaParameters && lambdaInfo is IrExpressionLambda) {
val extensionSize =
if (lambdaInfo.isExtensionLambda && !lambdaInfo.isBoundCallableReference)
lambdaInfo.invokeMethod.argumentTypes[0].size
else 0
val extensionSize = if (lambdaInfo.isExtensionLambda) lambdaInfo.invokeMethod.argumentTypes[0].size else 0
return when {
// v-- extensionSize v-- argsSizeOnStack
// |- extension -|- captured -|- real -|- locals -| old descriptor
@@ -425,10 +415,10 @@ class MethodInliner(
if (DEFAULT_LAMBDA_FAKE_CALL == owner) {
val index = name.substringAfter(DEFAULT_LAMBDA_FAKE_CALL).toInt()
val lambda = getFunctionalArgumentIfExists(index) as DefaultLambda
lambda.parameterOffsetsInDefault.zip(lambda.capturedVars).asReversed().forEach { (_, captured) ->
val originalBoundReceiverType = lambda.originalBoundReceiverType
if (lambda.isBoundCallableReference && AsmUtil.isPrimitive(originalBoundReceiverType)) {
StackValue.onStack(originalBoundReceiverType!!).put(captured.type, InstructionAdapter(this))
for (captured in lambda.capturedVars.asReversed()) {
lambda.originalBoundReceiverType?.let {
// The receiver is the only captured value; it needs to be boxed.
StackValue.onStack(it).put(captured.type, InstructionAdapter(this))
}
super.visitFieldInsn(
Opcodes.PUTSTATIC,
@@ -452,7 +442,7 @@ class MethodInliner(
else -> ""
}
val varName = if (!varSuffix.isEmpty() && name == AsmUtil.THIS) AsmUtil.INLINE_DECLARATION_SITE_THIS else name
val varName = if (varSuffix.isNotEmpty() && name == AsmUtil.THIS) AsmUtil.INLINE_DECLARATION_SITE_THIS else name
super.visitLocalVariable(varName + varSuffix, desc, signature, start, end, getNewIndex(index))
}
}
@@ -544,36 +534,36 @@ class MethodInliner(
cur.opcode == Opcodes.GETSTATIC -> {
val fieldInsnNode = cur as FieldInsnNode?
val className = fieldInsnNode!!.owner
if (isAnonymousSingletonLoad(className, fieldInsnNode.name)) {
recordTransformation(
AnonymousObjectTransformationInfo(
className, awaitClassReification, isAlreadyRegenerated(className), true,
inliningContext.nameGenerator
when {
isAnonymousSingletonLoad(className, fieldInsnNode.name) -> {
recordTransformation(
AnonymousObjectTransformationInfo(
className, awaitClassReification, isAlreadyRegenerated(className), true,
inliningContext.nameGenerator
)
)
)
awaitClassReification = false
} else if (isWhenMappingAccess(className, fieldInsnNode.name)) {
recordTransformation(
WhenMappingTransformationInfo(
className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode
awaitClassReification = false
}
isWhenMappingAccess(className, fieldInsnNode.name) -> {
recordTransformation(
WhenMappingTransformationInfo(
className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode
)
)
)
} else if (fieldInsnNode.isCheckAssertionsStatus()) {
fieldInsnNode.owner = inlineCallSiteInfo.ownerClassName
if (inliningContext.isInliningLambda) {
if (inliningContext.lambdaInfo!!.isCrossInline) {
assert(inliningContext.parent?.parent is RegeneratedClassContext) {
"$inliningContext grandparent shall be RegeneratedClassContext but got ${inliningContext.parent?.parent}"
}
inliningContext.parent!!.parent!!.generateAssertField = true
} else {
assert(inliningContext.parent != null) {
"$inliningContext parent shall not be null"
}
inliningContext.parent!!.generateAssertField = true
}
} else {
inliningContext.generateAssertField = true
}
fieldInsnNode.isCheckAssertionsStatus() -> {
fieldInsnNode.owner = inlineCallSiteInfo.ownerClassName
when {
// In inline function itself:
inliningContext.parent == null -> inliningContext
// In method of regenerated object - field should already exist:
inliningContext.parent is RegeneratedClassContext -> inliningContext.parent
// In lambda inlined into the root function:
inliningContext.parent.parent == null -> inliningContext.parent
// In lambda inlined into a method of a regenerated object:
else -> inliningContext.parent.parent as? RegeneratedClassContext
?: throw AssertionError("couldn't find class for \$assertionsDisabled (context = $inliningContext)")
}.generateAssertField = true
}
}
}
@@ -603,7 +593,7 @@ class MethodInliner(
assert(lambdaInfo.lambdaClassType.internalName == nodeRemapper.originalLambdaInternalName) {
"Wrong bytecode template for contract template: ${lambdaInfo.lambdaClassType.internalName} != ${nodeRemapper.originalLambdaInternalName}"
}
fieldInsn.name = FieldRemapper.foldName(fieldInsn.name)
fieldInsn.name = foldName(fieldInsn.name)
fieldInsn.opcode = Opcodes.PUTSTATIC
toDelete.addAll(stackTransformations)
}
@@ -643,9 +633,8 @@ class MethodInliner(
private fun replaceContinuationAccessesWithFakeContinuationsIfNeeded(processingNode: MethodNode) {
// in ir backend inline suspend lambdas do not use ALOAD 0 to get continuation, since they are generated as static functions
// instead they get continuation from parameter.
if (inliningContext.state.isIrBackend) return
val lambdaInfo = inliningContext.lambdaInfo ?: return
if (!lambdaInfo.isSuspend) return
if (lambdaInfo !is PsiExpressionLambda || !lambdaInfo.invokeMethodDescriptor.isSuspend) return
val sources = analyzeMethodNodeWithInterpreter(processingNode, Aload0Interpreter(processingNode))
val cfg = ControlFlowGraph.build(processingNode)
val aload0s = processingNode.instructions.asSequence().filter { it.opcode == Opcodes.ALOAD && it.safeAs<VarInsnNode>()?.`var` == 0 }
@@ -758,7 +747,7 @@ class MethodInliner(
ApiVersionCallsPreprocessingMethodTransformer(targetApiVersion).transform("fake", node)
}
val frames = analyzeMethodNodeWithInterpreter(node, BasicInterpreter())
val frames = FastStackAnalyzer("<fake>", node, FixStackInterpreter()).analyze()
val localReturnsNormalizer = LocalReturnsNormalizer()
@@ -825,7 +814,7 @@ class MethodInliner(
getFunctionalArgumentIfExists((insnNode as VarInsnNode).`var`)
insnNode is FieldInsnNode && insnNode.name.startsWith(CAPTURED_FIELD_FOLD_PREFIX) ->
findCapturedField(insnNode, nodeRemapper).functionalArgument
insnNode is FieldInsnNode && insnNode.isSuspendLambdaCapturedByOuterObjectOrLambda(inliningContext) ->
insnNode is FieldInsnNode && inliningContext.root.sourceCompilerForInline.isSuspendLambdaCapturedByOuterObjectOrLambda(insnNode.name) ->
NonInlineableArgumentForInlineableParameterCalledInSuspend
else ->
null
@@ -847,9 +836,9 @@ class MethodInliner(
if (inliningContext.isInliningLambda && inliningContext.lambdaInfo is IrExpressionLambda && !inliningContext.parent!!.isInliningLambda) {
val capturedVars = inliningContext.lambdaInfo.capturedVars
var offset = parameters.realParametersSizeOnStack
val map = capturedVars.map {
val map = capturedVars.associate {
offset to it.also { offset += it.type.size }
}.toMap()
}
var cur: AbstractInsnNode? = node.instructions.first
while (cur != null) {
@@ -894,6 +883,7 @@ class MethodInliner(
}
}
@Suppress("SameParameterValue")
private fun wrapException(originalException: Throwable, node: MethodNode, errorSuffix: String): RuntimeException {
return if (originalException is InlineException) {
InlineException("$errorPrefix: $errorSuffix", originalException)
@@ -906,7 +896,7 @@ class MethodInliner(
private class LocalReturn(
private val returnInsn: AbstractInsnNode,
private val insertBeforeInsn: AbstractInsnNode,
private val frame: Frame<BasicValue>
private val frame: Frame<FixStackValue>
) {
fun transform(insnList: InsnList, returnVariableIndex: Int) {
@@ -917,22 +907,19 @@ class MethodInliner(
if (expectedStackSize == actualStackSize) return
var stackSize = actualStackSize
val topValue = frame.getStack(stackSize - 1)
if (isReturnWithValue) {
val storeOpcode = Opcodes.ISTORE + returnInsn.opcode - Opcodes.IRETURN
insnList.insertBefore(insertBeforeInsn, VarInsnNode(storeOpcode, returnVariableIndex))
insnList.insertBefore(insertBeforeInsn, VarInsnNode(topValue.storeOpcode, returnVariableIndex))
stackSize--
}
while (stackSize > 0) {
val stackElementSize = frame.getStack(stackSize - 1).size
val popOpcode = if (stackElementSize == 1) Opcodes.POP else Opcodes.POP2
insnList.insertBefore(insertBeforeInsn, InsnNode(popOpcode))
insnList.insertBefore(insertBeforeInsn, InsnNode(frame.getStack(stackSize - 1).popOpcode))
stackSize--
}
if (isReturnWithValue) {
val loadOpcode = Opcodes.ILOAD + returnInsn.opcode - Opcodes.IRETURN
insnList.insertBefore(insertBeforeInsn, VarInsnNode(loadOpcode, returnVariableIndex))
insnList.insertBefore(insertBeforeInsn, VarInsnNode(topValue.loadOpcode, returnVariableIndex))
}
}
}
@@ -942,10 +929,10 @@ class MethodInliner(
private var returnVariableSize = 0
private var returnOpcode = -1
internal fun addLocalReturnToTransform(
fun addLocalReturnToTransform(
returnInsn: AbstractInsnNode,
insertBeforeInsn: AbstractInsnNode,
sourceValueFrame: Frame<BasicValue>
sourceValueFrame: Frame<FixStackValue>
) {
assert(isReturnOpcode(returnInsn.opcode)) { "return instruction expected" }
assert(returnOpcode < 0 || returnOpcode == returnInsn.opcode) { "Return op should be " + Printer.OPCODES[returnOpcode] + ", got " + Printer.OPCODES[returnInsn.opcode] }
@@ -954,11 +941,7 @@ class MethodInliner(
localReturns.add(LocalReturn(returnInsn, insertBeforeInsn, sourceValueFrame))
if (returnInsn.opcode != Opcodes.RETURN) {
returnVariableSize = if (returnInsn.opcode == Opcodes.LRETURN || returnInsn.opcode == Opcodes.DRETURN) {
2
} else {
1
}
returnVariableSize = if (returnInsn.opcode == Opcodes.LRETURN || returnInsn.opcode == Opcodes.DRETURN) 2 else 1
}
}

View File

@@ -5,11 +5,11 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
@@ -17,15 +17,6 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
import org.jetbrains.org.objectweb.asm.tree.analysis.*
fun parameterOffsets(isStatic: Boolean, valueParameters: List<JvmMethodParameterSignature>): Array<Int> {
var nextOffset = if (isStatic) 0 else 1
return Array(valueParameters.size) { index ->
nextOffset.also {
nextOffset += valueParameters[index].asmType.size
}
}
}
fun MethodNode.remove(instructions: Sequence<AbstractInsnNode>) =
instructions.forEach {
this@remove.instructions.remove(it)
@@ -136,7 +127,7 @@ internal class Aload0Interpreter(private val node: MethodNode) : BasicInterprete
internal fun AbstractInsnNode.isAload0() = opcode == Opcodes.ALOAD && (this as VarInsnNode).`var` == 0
internal fun analyzeMethodNodeWithInterpreter(node: MethodNode, interpreter: BasicInterpreter): Array<out Frame<BasicValue>?> {
val analyzer = object : Analyzer<BasicValue>(interpreter) {
val analyzer = object : FastMethodAnalyzer<BasicValue>("fake", node, interpreter) {
override fun newFrame(nLocals: Int, nStack: Int): Frame<BasicValue> {
return object : Frame<BasicValue>(nLocals, nStack) {
@@ -151,7 +142,7 @@ internal fun analyzeMethodNodeWithInterpreter(node: MethodNode, interpreter: Bas
}
try {
return analyzer.analyze("fake", node)
return analyzer.analyze()
} catch (e: AnalyzerException) {
throw RuntimeException(e)
}

View File

@@ -37,7 +37,7 @@ abstract class ObjectTransformer<out T : TransformationInfo>(@JvmField val trans
val classBuilder = state.factory.newVisitor(
JvmDeclarationOrigin.NO_ORIGIN,
Type.getObjectType(transformationInfo.newClassName),
inliningContext.root.sourceCompilerForInline.callsiteFile!!
inliningContext.callSiteInfo.file!!
)
return RemappingClassBuilder(

View File

@@ -107,22 +107,5 @@ class ParametersBuilder private constructor() {
fun newBuilder(): ParametersBuilder {
return ParametersBuilder()
}
@JvmOverloads
@JvmStatic
fun initializeBuilderFrom(
objectType: Type, descriptor: String, inlineLambda: LambdaInfo? = null, isStatic: Boolean = false
): ParametersBuilder {
val builder = newBuilder()
if (inlineLambda?.hasDispatchReceiver != false && !isStatic) {
//skipped this for inlined lambda cause it will be removed
builder.addThis(objectType, inlineLambda != null).functionalArgument = inlineLambda
}
for (type in Type.getArgumentTypes(descriptor)) {
builder.addNextParameter(type, false)
}
return builder
}
}
}

View File

@@ -5,19 +5,14 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getMethodAsmFlags
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
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.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
@@ -26,39 +21,33 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlinableParameterExpression
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class PsiInlineCodegen(
codegen: ExpressionCodegen,
state: GenerationState,
function: FunctionDescriptor,
methodOwner: Type,
private val functionDescriptor: FunctionDescriptor,
signature: JvmMethodSignature,
typeParameterMappings: TypeParameterMappings<KotlinType>,
sourceCompiler: SourceCompilerForInline,
private val actualDispatchReceiver: Type = methodOwner
private val methodOwner: Type,
private val actualDispatchReceiver: Type,
reportErrorsOn: KtElement,
) : InlineCodegen<ExpressionCodegen>(
codegen, state, function, methodOwner, signature, typeParameterMappings, sourceCompiler,
codegen, state, signature, typeParameterMappings, sourceCompiler,
ReifiedTypeInliner(
typeParameterMappings, PsiInlineIntrinsicsSupport(state), codegen.typeSystem,
typeParameterMappings, PsiInlineIntrinsicsSupport(state, reportErrorsOn), codegen.typeSystem,
state.languageVersionSettings, state.unifiedNullChecks
),
), CallGenerator {
override fun generateAssertFieldIfNeeded(info: RootInliningContext) {
if (info.generateAssertField) {
codegen.parentCodegen.generateAssertField()
}
}
override fun generateAssertField() =
codegen.parentCodegen.generateAssertField()
override fun genCallInner(
callableMethod: Callable,
@@ -66,13 +55,26 @@ class PsiInlineCodegen(
callDefault: Boolean,
codegen: ExpressionCodegen
) {
(sourceCompiler as PsiSourceCompilerForInline).callDefault = callDefault
assert(hiddenParameters.isEmpty()) { "putHiddenParamsIntoLocals() should be called after processHiddenParameters()" }
if (!state.globalInlineContext.enterIntoInlining(functionDescriptor, resolvedCall?.call?.callElement)) {
generateStub(resolvedCall?.call?.callElement?.text ?: "<no source>", codegen)
return
}
try {
val registerLineNumber = registerLineNumberAfterwards(resolvedCall)
performInline(resolvedCall?.typeArguments?.keys?.toList(), callDefault, callDefault, codegen.typeSystem, registerLineNumber)
for (info in expressionMap.values) {
if (info is PsiExpressionLambda) {
// Can't be done immediately in `rememberClosure` for some reason:
info.generateLambdaBody(sourceCompiler)
// Requires `generateLambdaBody` first if the closure is non-empty (for bound callable references,
// or indeed any callable references, it *is* empty, so this was done in `rememberClosure`):
if (!info.isBoundCallableReference) {
putClosureParametersOnStack(info, null)
}
}
}
performInline(registerLineNumber, functionDescriptor.isInlineOnly())
} finally {
state.globalInlineContext.exitFromInlining()
}
@@ -84,46 +86,29 @@ class PsiInlineCodegen(
return parentIfCondition.isAncestor(callElement, false)
}
override fun processAndPutHiddenParameters(justProcess: Boolean) {
if (getMethodAsmFlags(functionDescriptor, sourceCompiler.contextKind, state) and Opcodes.ACC_STATIC == 0) {
invocationParamBuilder.addNextParameter(methodOwner, false, actualDispatchReceiver)
}
private val hiddenParameters = mutableListOf<Pair<ParameterInfo, Int>>()
override fun processHiddenParameters() {
if (!DescriptorAsmUtil.isStaticMethod((sourceCompiler as PsiSourceCompilerForInline).context.contextKind, functionDescriptor)) {
hiddenParameters += invocationParamBuilder.addNextParameter(methodOwner, false, actualDispatchReceiver) to
codegen.frameMap.enterTemp(methodOwner)
}
for (param in jvmSignature.valueParameters) {
if (param.kind == JvmMethodParameterKind.VALUE) {
break
}
invocationParamBuilder.addNextParameter(param.asmType, false)
hiddenParameters += invocationParamBuilder.addNextParameter(param.asmType, false) to
codegen.frameMap.enterTemp(param.asmType)
}
invocationParamBuilder.markValueParametersStart()
val hiddenParameters = invocationParamBuilder.buildParameters().parameters
delayedHiddenWriting = recordParameterValueInLocalVal(justProcess, false, *hiddenParameters.toTypedArray())
}
override fun putClosureParametersOnStack(next: LambdaInfo, functionReferenceReceiver: StackValue?) {
activeLambda = next
when (next) {
is PsiExpressionLambda -> codegen.pushClosureOnStack(next.classDescriptor, true, this, functionReferenceReceiver)
is DefaultLambda -> rememberCapturedForDefaultLambda(next)
else -> throw RuntimeException("Unknown lambda: $next")
override fun putHiddenParamsIntoLocals() {
for (i in hiddenParameters.indices.reversed()) {
val (param, offset) = hiddenParameters[i]
StackValue.local(offset, param.type).store(StackValue.onStack(param.typeOnStack), codegen.visitor)
}
activeLambda = null
}
private fun getBoundCallableReferenceReceiver(argumentExpression: KtExpression): ReceiverValue? {
val deparenthesized = KtPsiUtil.deparenthesize(argumentExpression) as? KtCallableReferenceExpression ?: return null
val resolvedCall = deparenthesized.callableReference.getResolvedCallWithAssert(state.bindingContext)
return JvmCodegenUtil.getBoundCallableReferenceReceiver(resolvedCall)
}
/*lambda or callable reference*/
private fun isInliningParameter(expression: KtExpression, valueParameterDescriptor: ValueParameterDescriptor): Boolean {
//TODO deparenthesize typed
val deparenthesized = KtPsiUtil.deparenthesize(expression)
return InlineUtil.isInlineParameter(valueParameterDescriptor) && isInlinableParameterExpression(deparenthesized)
hiddenParameters.clear()
}
override fun genValueAndPut(
@@ -137,24 +122,10 @@ class PsiInlineCodegen(
"which cannot be declared in Kotlin and thus be inline: $codegen"
}
if (isInliningParameter(argumentExpression, valueParameterDescriptor)) {
val lambdaInfo = rememberClosure(argumentExpression, parameterType.type, valueParameterDescriptor)
val receiverValue = getBoundCallableReferenceReceiver(argumentExpression)
if (receiverValue != null) {
val receiver = codegen.generateReceiverValue(receiverValue, false)
val receiverKotlinType = receiver.kotlinType
val boxedReceiver =
if (receiverKotlinType != null)
DescriptorAsmUtil.boxType(receiver.type, receiverKotlinType, state.typeMapper)
else
AsmUtil.boxType(receiver.type)
putClosureParametersOnStack(
lambdaInfo,
StackValue.coercion(receiver, boxedReceiver, receiverKotlinType)
)
}
val isInlineParameter = InlineUtil.isInlineParameter(valueParameterDescriptor)
//TODO deparenthesize typed
if (isInlineParameter && isInlinableParameterExpression(KtPsiUtil.deparenthesize(argumentExpression))) {
rememberClosure(argumentExpression, parameterType.type, valueParameterDescriptor)
} else {
val value = codegen.gen(argumentExpression)
val kind = when {
@@ -173,52 +144,47 @@ class PsiInlineCodegen(
private fun isCallSiteIsSuspend(descriptor: ValueParameterDescriptor): Boolean =
state.bindingContext[CodegenBinding.CALL_SITE_IS_SUSPEND_FOR_CROSSINLINE_LAMBDA, descriptor] == true
private fun rememberClosure(expression: KtExpression, type: Type, parameter: ValueParameterDescriptor): LambdaInfo {
private fun rememberClosure(expression: KtExpression, type: Type, parameter: ValueParameterDescriptor) {
val ktLambda = KtPsiUtil.deparenthesize(expression)
assert(isInlinableParameterExpression(ktLambda)) { "Couldn't find inline expression in ${expression.text}" }
return PsiExpressionLambda(
ktLambda!!, state.typeMapper, state.languageVersionSettings,
parameter.isCrossinline, getBoundCallableReferenceReceiver(expression) != null
).also { lambda ->
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
closureInfo.functionalArgument = lambda
expressionMap[closureInfo.index] = lambda
val boundReceiver = if (ktLambda is KtCallableReferenceExpression) {
val resolvedCall = ktLambda.callableReference.getResolvedCallWithAssert(state.bindingContext)
JvmCodegenUtil.getBoundCallableReferenceReceiver(resolvedCall)
} else null
val lambda = PsiExpressionLambda(ktLambda!!, state, parameter.isCrossinline, boundReceiver != null)
rememberClosure(type, parameter.index, lambda)
if (boundReceiver != null) {
// Has to be done immediately to preserve evaluation order.
val receiver = codegen.generateReceiverValue(boundReceiver, false)
val receiverKotlinType = receiver.kotlinType
val boxedReceiver =
if (receiverKotlinType != null)
DescriptorAsmUtil.boxType(receiver.type, receiverKotlinType, state.typeMapper)
else
AsmUtil.boxType(receiver.type)
val receiverValue = StackValue.coercion(receiver, boxedReceiver, receiverKotlinType)
putClosureParametersOnStack(lambda, receiverValue)
}
}
override fun putValueIfNeeded(parameterType: JvmKotlinType, value: StackValue, kind: ValueKind, parameterIndex: Int) {
if (processDefaultMaskOrMethodHandler(value, kind)) return
var activeLambda: PsiExpressionLambda? = null
private set
assert(maskValues.isEmpty()) { "Additional default call arguments should be last ones, but $value" }
putArgumentOrCapturedToLocalVal(parameterType, value, -1, parameterIndex, kind)
private fun putClosureParametersOnStack(next: PsiExpressionLambda, receiverValue: StackValue?) {
activeLambda = next
codegen.pushClosureOnStack(next.classDescriptor, true, this, receiverValue)
activeLambda = null
}
override fun putCapturedValueOnStack(stackValue: StackValue, valueType: Type, paramIndex: Int) {
putArgumentOrCapturedToLocalVal(
JvmKotlinType(stackValue.type, stackValue.kotlinType), stackValue, paramIndex, paramIndex, ValueKind.CAPTURED
)
}
override fun putValueIfNeeded(parameterType: JvmKotlinType, value: StackValue, kind: ValueKind, parameterIndex: Int) =
putArgumentToLocalVal(parameterType, value, parameterIndex, kind)
override fun putCapturedValueOnStack(stackValue: StackValue, valueType: Type, paramIndex: Int) =
putCapturedToLocalVal(stackValue, activeLambda!!.capturedVars[paramIndex], stackValue.kotlinType)
override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>) = Unit
override fun putHiddenParamsIntoLocals() {
assert(delayedHiddenWriting != null) { "processAndPutHiddenParameters(true) should be called before putHiddenParamsIntoLocals" }
delayedHiddenWriting!!.invoke()
delayedHiddenWriting = null
}
override fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda> {
return expandMaskConditionsAndUpdateVariableNodes(
node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex,
extractDefaultLambdaOffsetAndDescriptor(jvmSignature, functionDescriptor),
::PsiDefaultLambda
)
}
override fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean =
memberDescriptor is DescriptorWithContainerSource
}
private val FunctionDescriptor.explicitParameters
@@ -226,12 +192,10 @@ private val FunctionDescriptor.explicitParameters
class PsiExpressionLambda(
expression: KtExpression,
private val typeMapper: KotlinTypeMapper,
private val languageVersionSettings: LanguageVersionSettings,
isCrossInline: Boolean,
override val isBoundCallableReference: Boolean
) : ExpressionLambda(isCrossInline) {
private val state: GenerationState,
val isCrossInline: Boolean,
val isBoundCallableReference: Boolean
) : ExpressionLambda() {
override val lambdaClassType: Type
override val invokeMethod: Method
@@ -240,10 +204,8 @@ class PsiExpressionLambda(
override val invokeMethodParameters: List<KotlinType?>
get() {
val actualInvokeDescriptor = if (isSuspend)
getOrCreateJvmSuspendFunctionView(
invokeMethodDescriptor, languageVersionSettings.isReleaseCoroutines(), typeMapper.bindingContext
)
val actualInvokeDescriptor = if (invokeMethodDescriptor.isSuspend)
getOrCreateJvmSuspendFunctionView(invokeMethodDescriptor, state)
else
invokeMethodDescriptor
return actualInvokeDescriptor.explicitParameters.map { it.returnType }
@@ -260,12 +222,10 @@ class PsiExpressionLambda(
override val returnLabels: Map<String, Label?>
override val isSuspend: Boolean
val closure: CalculatedClosure
init {
val bindingContext = typeMapper.bindingContext
val bindingContext = state.bindingContext
val function = bindingContext.get(BindingContext.FUNCTION, functionWithBodyOrCallableReference)
if (function == null && expression is KtCallableReferenceExpression) {
val variableDescriptor =
@@ -273,7 +233,7 @@ class PsiExpressionLambda(
?: throw AssertionError("Reference expression not resolved to variable descriptor with accessors: ${expression.getText()}")
classDescriptor = bindingContext.get(CodegenBinding.CLASS_FOR_CALLABLE, variableDescriptor)
?: throw IllegalStateException("Class for callable not found: $variableDescriptor\n${expression.text}")
lambdaClassType = typeMapper.mapClass(classDescriptor)
lambdaClassType = state.typeMapper.mapClass(classDescriptor)
val getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor)
invokeMethodDescriptor = PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor)
val resolvedCall = expression.callableReference.getResolvedCallWithAssert(bindingContext)
@@ -288,24 +248,25 @@ class PsiExpressionLambda(
closure = bindingContext.get(CodegenBinding.CLOSURE, classDescriptor)
?: throw AssertionError("null closure for lambda ${expression.text}")
returnLabels = InlineCodegen.getDeclarationLabels(expression, invokeMethodDescriptor).associateWith { null }
invokeMethod = typeMapper.mapAsmMethod(invokeMethodDescriptor)
isSuspend = invokeMethodDescriptor.isSuspend
returnLabels = getDeclarationLabels(expression, invokeMethodDescriptor).associateWith { null }
invokeMethod = state.typeMapper.mapAsmMethod(invokeMethodDescriptor)
}
// This can only be computed after generating the body, hence `lazy`.
override val capturedVars: List<CapturedParamDesc> by lazy {
arrayListOf<CapturedParamDesc>().apply {
val captureThis = closure.capturedOuterClassDescriptor
if (captureThis != null) {
add(capturedParamDesc(AsmUtil.CAPTURED_THIS_FIELD, typeMapper.mapType(captureThis.defaultType), isSuspend = false))
add(capturedParamDesc(AsmUtil.CAPTURED_THIS_FIELD, state.typeMapper.mapType(captureThis.defaultType), isSuspend = false))
}
val capturedReceiver = closure.capturedReceiverFromOuterContext
if (capturedReceiver != null) {
val fieldName = closure.getCapturedReceiverFieldName(typeMapper.bindingContext, languageVersionSettings)
val type = typeMapper.mapType(capturedReceiver).let {
if (isBoundCallableReference) AsmUtil.boxType(it) else it
}
val fieldName = closure.getCapturedReceiverFieldName(state.typeMapper.bindingContext, state.languageVersionSettings)
val type = if (isBoundCallableReference)
state.typeMapper.mapType(capturedReceiver, null, TypeMappingMode.GENERIC_ARGUMENT)
else
state.typeMapper.mapType(capturedReceiver)
add(capturedParamDesc(fieldName, type, isSuspend = false))
}
@@ -319,40 +280,3 @@ class PsiExpressionLambda(
val isPropertyReference: Boolean
get() = propertyReferenceInfo != null
}
class PsiDefaultLambda(
override val lambdaClassType: Type,
capturedArgs: Array<Type>,
private val parameterDescriptor: ValueParameterDescriptor,
offset: Int,
needReification: Boolean
) : DefaultLambda(capturedArgs, parameterDescriptor.isCrossinline, offset, needReification) {
private lateinit var invokeMethodDescriptor: FunctionDescriptor
override val invokeMethodParameters: List<KotlinType?>
get() = invokeMethodDescriptor.explicitParameters.map { it.returnType }
override val invokeMethodReturnType: KotlinType?
get() = invokeMethodDescriptor.returnType
override fun mapAsmMethod(sourceCompiler: SourceCompilerForInline, isPropertyReference: Boolean): Method {
val substitutedDescriptor = parameterDescriptor.type.memberScope
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND)
.single()
invokeMethodDescriptor = when {
// Property references: `(A) -> B` => `get(Any?): Any?`
isPropertyReference -> substitutedDescriptor.original
// Suspend function references: `suspend (A) -> B` => `invoke(A, Continuation<B>): Any?`
// TODO: default suspend lambdas are currently uninlinable
parameterDescriptor.type.isSuspendFunctionType ->
getOrCreateJvmSuspendFunctionView(
substitutedDescriptor,
sourceCompiler.state.languageVersionSettings.isReleaseCoroutines(),
sourceCompiler.state.bindingContext
)
// Non-suspend function references and lambdas: `(A) -> B` => `invoke(A): B`
else -> substitutedDescriptor
}
return sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod
}
}

View File

@@ -5,13 +5,19 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.TYPEOF_SUSPEND_TYPE
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.org.objectweb.asm.Type
@@ -19,7 +25,10 @@ import org.jetbrains.org.objectweb.asm.Type.INT_TYPE
import org.jetbrains.org.objectweb.asm.Type.VOID_TYPE
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class PsiInlineIntrinsicsSupport(private val state: GenerationState) : ReifiedTypeInliner.IntrinsicsSupport<KotlinType> {
class PsiInlineIntrinsicsSupport(
override val state: GenerationState,
private val reportErrorsOn: KtElement,
) : ReifiedTypeInliner.IntrinsicsSupport<KotlinType> {
override fun putClassInstance(v: InstructionAdapter, type: KotlinType) {
DescriptorAsmUtil.putJavaLangClassInstance(v, state.typeMapper.mapType(type), type, state.typeMapper)
}
@@ -56,5 +65,18 @@ class PsiInlineIntrinsicsSupport(private val state: GenerationState) : ReifiedTy
)
}
override fun isMutableCollectionType(type: KotlinType): Boolean {
val classifier = type.constructor.declarationDescriptor
return classifier is ClassDescriptor && JavaToKotlinClassMap.isMutable(classifier.fqNameUnsafe)
}
override fun toKotlinType(type: KotlinType): KotlinType = type
override fun reportSuspendTypeUnsupported() {
state.diagnostics.report(TYPEOF_SUSPEND_TYPE.on(reportErrorsOn))
}
override fun reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameterName: Name) {
state.diagnostics.report(TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND.on(reportErrorsOn, typeParameterName.asString()))
}
}

View File

@@ -0,0 +1,443 @@
/*
* 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 com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.context.*
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.*
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.jvm.annotations.isCallableMemberCompiledToJvmDefault
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
import org.jetbrains.kotlin.types.expressions.LabelResolver
import org.jetbrains.kotlin.utils.addIfNotNull
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.commons.Method
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class PsiSourceCompilerForInline(
private val codegen: ExpressionCodegen,
override val callElement: KtElement,
private val functionDescriptor: FunctionDescriptor
) : SourceCompilerForInline {
override val state
get() = codegen.state
private val additionalInnerClasses = mutableListOf<ClassDescriptor>()
val context = getContext(
functionDescriptor,
functionDescriptor,
codegen.state,
DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile,
additionalInnerClasses
) as MethodContext
override val callElementText: String by lazy { callElement.text }
override val inlineCallSiteInfo: InlineCallSiteInfo
get() {
var context = codegen.getContext()
var parentCodegen = codegen.parentCodegen
while (context is InlineLambdaContext) {
val closureContext = context.getParentContext()
assert(closureContext is ClosureContext) { "Parent context of inline lambda should be closure context" }
assert(closureContext.parentContext is MethodContext) { "Closure context should appear in method context" }
context = closureContext.parentContext as MethodContext
assert(parentCodegen is FakeMemberCodegen) { "Parent codegen of inlined lambda should be FakeMemberCodegen" }
parentCodegen = (parentCodegen as FakeMemberCodegen).delegate
}
val signature = codegen.state.typeMapper.mapSignatureSkipGeneric(context.functionDescriptor, context.contextKind)
return InlineCallSiteInfo(
parentCodegen.className,
signature.asmMethod,
context.functionDescriptor.isInlineOrInsideInline(),
callElement.containingFile,
CodegenUtil.getLineNumberForElement(callElement, false) ?: 0
)
}
override val sourceMapper
get() = codegen.parentCodegen.orCreateSourceMapper
override fun generateLambdaBody(lambdaInfo: ExpressionLambda, reifiedTypeParameters: ReifiedTypeParametersUsages): SMAPAndMethodNode {
require(lambdaInfo is PsiExpressionLambda)
val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor
val jvmMethodSignature = state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor)
val asmMethod = jvmMethodSignature.asmMethod
val methodNode = MethodNode(
Opcodes.API_VERSION, DescriptorAsmUtil.getMethodAsmFlags(invokeMethodDescriptor, OwnerKind.IMPLEMENTATION, state),
asmMethod.name, asmMethod.descriptor, null, null
)
val adapter = wrapWithMaxLocalCalc(methodNode)
val closureContext = when {
lambdaInfo.isPropertyReference ->
codegen.getContext().intoAnonymousClass(lambdaInfo.classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
invokeMethodDescriptor.isSuspend ->
codegen.getContext().intoCoroutineClosure(
getOrCreateJvmSuspendFunctionView(invokeMethodDescriptor, state), invokeMethodDescriptor, codegen, state.typeMapper
)
else -> codegen.getContext().intoClosure(invokeMethodDescriptor, codegen, state.typeMapper)
}
val context = closureContext.intoInlinedLambda(invokeMethodDescriptor, lambdaInfo.isCrossInline, lambdaInfo.isPropertyReference)
val smap = generateMethodBody(
adapter, invokeMethodDescriptor, context,
lambdaInfo.functionWithBodyOrCallableReference,
jvmMethodSignature, lambdaInfo
)
adapter.visitMaxs(-1, -1)
return SMAPAndMethodNode(methodNode, smap)
}
private fun generateMethodBody(
adapter: MethodVisitor,
descriptor: FunctionDescriptor,
context: MethodContext,
expression: KtExpression,
jvmMethodSignature: JvmMethodSignature,
lambdaInfo: PsiExpressionLambda?
): SMAP {
val isLambda = lambdaInfo != null
// Wrapping for preventing marking actual parent codegen as containing reified markers
val parentCodegen = FakeMemberCodegen(
codegen.parentCodegen, expression, context.parentContext as FieldOwnerContext<*>,
if (isLambda)
codegen.parentCodegen.className
else
state.typeMapper.mapImplementationOwner(descriptor).internalName,
if (isLambda) emptyList() else additionalInnerClasses,
isLambda
)
val strategy = when (expression) {
is KtCallableReferenceExpression -> {
val resolvedCall = expression.callableReference.getResolvedCallWithAssert(state.bindingContext)
val receiverKotlinType = JvmCodegenUtil.getBoundCallableReferenceReceiver(resolvedCall)?.type
val receiverType = receiverKotlinType?.let(state.typeMapper::mapType)
val boundReceiverJvmKotlinType = receiverType?.let { JvmKotlinType(receiverType, receiverKotlinType) }
if (isLambda && lambdaInfo!!.isPropertyReference) {
val asmType = state.typeMapper.mapClass(lambdaInfo.classDescriptor)
val info = lambdaInfo.propertyReferenceInfo
PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
true, info!!.getFunction, info.target, asmType,
boundReceiverJvmKotlinType,
lambdaInfo.functionWithBodyOrCallableReference, state, true
)
} else {
FunctionReferenceGenerationStrategy(state, descriptor, resolvedCall, boundReceiverJvmKotlinType, null, true)
}
}
is KtFunctionLiteral -> ClosureGenerationStrategy(state, expression as KtDeclarationWithBody)
else -> FunctionGenerationStrategy.FunctionDefault(state, expression as KtDeclarationWithBody)
}
FunctionCodegen.generateMethodBody(
adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen, state.jvmDefaultMode,
state.languageVersionSettings.isReleaseCoroutines()
)
if (isLambda) {
codegen.propagateChildReifiedTypeParametersUsages(parentCodegen.reifiedTypeParametersUsages)
}
return SMAP(parentCodegen.orCreateSourceMapper.resultMappings)
}
@Suppress("UNCHECKED_CAST")
private class FakeMemberCodegen(
val delegate: MemberCodegen<*>,
declaration: KtElement,
codegenContext: FieldOwnerContext<*>,
private val className: String,
private val parentAsInnerClasses: List<ClassDescriptor>,
private val isInlineLambdaCodegen: Boolean
) : MemberCodegen<KtPureElement>(delegate as MemberCodegen<KtPureElement>, declaration, codegenContext) {
override fun generateDeclaration() {
throw IllegalStateException()
}
override fun generateBody() {
throw IllegalStateException()
}
override fun generateKotlinMetadataAnnotation() {
throw IllegalStateException()
}
override fun getInlineNameGenerator(): NameGenerator {
return delegate.inlineNameGenerator
}
override //TODO: obtain name from context
fun getClassName(): String {
return className
}
override fun addParentsToInnerClassesIfNeeded(innerClasses: MutableCollection<ClassDescriptor>) {
if (isInlineLambdaCodegen) {
super.addParentsToInnerClassesIfNeeded(innerClasses)
} else {
innerClasses.addAll(parentAsInnerClasses)
}
}
override fun generateAssertField() {
delegate.generateAssertField()
}
}
private fun getDirectMemberAndCallableFromObject(): CallableMemberDescriptor {
val directMember = JvmCodegenUtil.getDirectMember(functionDescriptor)
return (directMember as? ImportedFromObjectCallableDescriptor<*>)?.callableFromObject ?: directMember
}
internal var callDefault: Boolean = false
private fun mapDefault(): Method {
// This is all available in the `Callable` passed to `PsiInlineCodegen.genCallInner`, but it's not forwarded through the inliner...
var result = state.typeMapper.mapDefaultMethod(functionDescriptor, context.contextKind)
if (result.name.contains("-") &&
!state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME) &&
classFileContainsMethod(functionDescriptor, state, result) == false
) {
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = true
result = state.typeMapper.mapDefaultMethod(functionDescriptor, context.contextKind)
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = false
}
return result
}
override fun compileInlineFunction(jvmSignature: JvmMethodSignature): SMAPAndMethodNode {
generateInlineIntrinsic(state.languageVersionSettings, functionDescriptor, jvmSignature.asmMethod, codegen.typeSystem)?.let {
return it
}
val asmMethod = if (callDefault) mapDefault() else jvmSignature.asmMethod
if (asmMethod.name != functionDescriptor.name.asString()) {
KotlinLookupLocation(callElement).location?.let {
state.trackLookup(DescriptorUtils.getFqNameSafe(functionDescriptor.containingDeclaration), asmMethod.name, it)
}
}
val directMember = getDirectMemberAndCallableFromObject()
if (directMember is DescriptorWithContainerSource) {
val containerId = KotlinTypeMapper.getContainingClassesForDeserializedCallable(directMember).implClassId
val isMangled = requiresFunctionNameManglingForReturnType(functionDescriptor)
return loadCompiledInlineFunction(containerId, asmMethod, functionDescriptor.isSuspend, isMangled, state)
}
val element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor) as? KtDeclarationWithBody
?: throw IllegalStateException("Couldn't find declaration for function $functionDescriptor")
val node = MethodNode(
Opcodes.API_VERSION,
DescriptorAsmUtil.getMethodAsmFlags(functionDescriptor, context.contextKind, state) or
if (callDefault) Opcodes.ACC_STATIC else 0,
asmMethod.name,
asmMethod.descriptor, null, null
)
//for maxLocals calculation
val maxCalcAdapter = wrapWithMaxLocalCalc(node)
val smap = if (callDefault) {
val implementationOwner = state.typeMapper.mapImplementationOwner(functionDescriptor)
val parentCodegen = FakeMemberCodegen(
codegen.parentCodegen, element, context.parentContext as FieldOwnerContext<*>,
implementationOwner.internalName,
additionalInnerClasses,
false
)
if (element !is KtNamedFunction) {
throw IllegalStateException("Property accessors with default parameters not supported $functionDescriptor")
}
FunctionCodegen.generateDefaultImplBody(
context, functionDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
element as KtNamedFunction?, parentCodegen, asmMethod
)
SMAP(parentCodegen.orCreateSourceMapper.resultMappings)
} else {
generateMethodBody(maxCalcAdapter, functionDescriptor, context, element, jvmSignature, null)
}
maxCalcAdapter.visitMaxs(-1, -1)
maxCalcAdapter.visitEnd()
return SMAPAndMethodNode(node, smap)
}
override fun hasFinallyBlocks() = codegen.hasFinallyBlocks()
override fun generateFinallyBlocks(finallyNode: MethodNode, curFinallyDepth: Int, returnType: Type, afterReturnLabel: Label, target: Label?) {
// TODO use the target label for non-local break/continue
ExpressionCodegen(
finallyNode, codegen.frameMap, codegen.returnType,
codegen.getContext(), codegen.state, codegen.parentCodegen
).also {
it.addBlockStackElementsForNonLocalReturns(codegen.blockStackElements, curFinallyDepth)
}.generateFinallyBlocksIfNeeded(returnType, null, afterReturnLabel)
}
override val isCallInsideSameModuleAsCallee: Boolean
get() = JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), codegen.state.outDirectory)
override val isFinallyMarkerRequired: Boolean
get() = isFinallyMarkerRequired(codegen.getContext())
override fun isSuspendLambdaCapturedByOuterObjectOrLambda(name: String): Boolean {
// We cannot find the lambda in captured parameters: it came from object outside of the our reach:
// this can happen when the lambda capture by non-transformed closure:
// inline fun inlineMe(crossinline c: suspend() -> Unit) = suspend { c() }
// inline fun inlineMe2(crossinline c: suspend() -> Unit) = suspend { inlineMe { c() }() }
// Suppose, we inline inlineMe into inlineMe2: the only knowledge we have about inlineMe$1 is captured receiver (this$0)
// Thus, transformed lambda from inlineMe, inlineMe3$$inlined$inlineMe2$1 contains the following bytecode
// ALOAD 0
// GETFIELD inlineMe2$1$invokeSuspend$$inlined$inlineMe$1.this$0 : LScratchKt$inlineMe2$1;
// GETFIELD inlineMe2$1.$c : Lkotlin/jvm/functions/Function1;
// Since inlineMe2's lambda is outside of reach of the inliner, find crossinline parameter from compilation context:
var container: DeclarationDescriptor = codegen.getContext().functionDescriptor
while (container !is ClassDescriptor) {
container = container.containingDeclaration ?: return false
}
var classDescriptor: ClassDescriptor? = container
while (classDescriptor != null) {
val closure = state.bindingContext[CodegenBinding.CLOSURE, classDescriptor] ?: return false
for ((param, value) in closure.captureVariables) {
if (param is ValueParameterDescriptor && value.fieldName == name) {
return param.type.isSuspendFunctionTypeOrSubtype
}
}
classDescriptor = closure.capturedOuterClassDescriptor
}
return false
}
override fun getContextLabels(): Map<String, Label?> {
val context = codegen.getContext()
val parentContext = context.parentContext
val descriptor = if (parentContext is ClosureContext && parentContext.originalSuspendLambdaDescriptor != null) {
parentContext.originalSuspendLambdaDescriptor!!
} else context.contextDescriptor
val labels = getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor)
return labels.associateWith { null } // TODO add break/continue labels
}
override fun reportSuspensionPointInsideMonitor(stackTraceElement: String) {
org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor(callElement, state, stackTraceElement)
}
companion object {
fun getContext(
descriptor: DeclarationDescriptor,
innerDescriptor: DeclarationDescriptor,
state: GenerationState,
sourceFile: KtFile?,
additionalInners: MutableList<ClassDescriptor>
): CodegenContext<*> {
if (descriptor is PackageFragmentDescriptor) {
//no inners
return PackageContext(descriptor, state.rootContext, null, sourceFile)
}
val container = descriptor.containingDeclaration ?: error("No container for descriptor: $descriptor")
val containerContext = getContext(
container,
descriptor,
state,
sourceFile,
additionalInners
)
return when (descriptor) {
is ScriptDescriptor -> {
val earlierScripts = state.scriptSpecific.earlierScriptsForReplInterpreter
containerContext.intoScript(
descriptor,
earlierScripts ?: emptyList(),
descriptor as ClassDescriptor, state.typeMapper
)
}
is ClassDescriptor -> {
val kind =
when {
DescriptorUtils.isInterface(descriptor) &&
innerDescriptor !is ClassDescriptor &&
!innerDescriptor.isCallableMemberCompiledToJvmDefault(state.jvmDefaultMode) ->
OwnerKind.DEFAULT_IMPLS
else ->
OwnerKind.IMPLEMENTATION
}
additionalInners.addIfNotNull(
InnerClassConsumer.classForInnerClassRecord(descriptor, kind == OwnerKind.DEFAULT_IMPLS)
)
if (descriptor.isInlineClass()) {
containerContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state)
.intoClass(descriptor, OwnerKind.ERASED_INLINE_CLASS, state)
} else {
containerContext.intoClass(descriptor, kind, state)
}
}
is FunctionDescriptor -> {
containerContext.intoFunction(descriptor)
}
else -> {
throw IllegalStateException("Couldn't build context for $descriptor")
}
}
}
}
}
fun DeclarationDescriptor.isInlineOrInsideInline(): Boolean =
if (this is FunctionDescriptor && isInline) true
else containingDeclaration?.isInlineOrInsideInline() == true
fun getDeclarationLabels(lambdaOrFun: PsiElement?, descriptor: DeclarationDescriptor): Set<String> {
val result = HashSet<String>()
if (lambdaOrFun != null) {
val label = LabelResolver.getLabelNameIfAny(lambdaOrFun)
if (label != null) {
result.add(label.asString())
}
}
if (!ExpressionTypingUtils.isFunctionLiteral(descriptor)) {
if (!descriptor.name.isSpecial) {
result.add(descriptor.name.asString())
}
result.add(FIRST_FUN_LABEL)
}
return result
}

View File

@@ -20,9 +20,11 @@ import org.jetbrains.kotlin.codegen.generateAsCast
import org.jetbrains.kotlin.codegen.generateIsCheck
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
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
@@ -63,11 +65,18 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
}
interface IntrinsicsSupport<KT : KotlinTypeMarker> {
val state: GenerationState
fun putClassInstance(v: InstructionAdapter, type: KT)
fun generateTypeParameterContainer(v: InstructionAdapter, typeParameter: TypeParameterMarker)
fun isMutableCollectionType(type: KT): Boolean
fun toKotlinType(type: KT): KotlinType
fun reportSuspendTypeUnsupported()
fun reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameterName: Name)
}
companion object {

View File

@@ -6,428 +6,109 @@
package org.jetbrains.kotlin.codegen.inline
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.context.*
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.jvm.annotations.isCallableMemberCompiledToJvmDefault
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.incremental.components.LocationInfo
import org.jetbrains.kotlin.incremental.components.Position
import org.jetbrains.kotlin.incremental.components.ScopeKind
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.utils.addIfNotNull
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.commons.Method
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import kotlin.properties.Delegates
class InlineCallSiteInfo(
val ownerClassName: String,
val method: Method,
val isInlineOrInsideInline: Boolean,
val file: PsiFile?,
val lineNumber: Int
)
interface SourceCompilerForInline {
val state: GenerationState
val callElement: Any
val lookupLocation: LookupLocation
val callElementText: String
val callsiteFile: PsiFile?
val contextKind: OwnerKind
val inlineCallSiteInfo: InlineCallSiteInfo
val lazySourceMapper: SourceMapper
val sourceMapper: SourceMapper
fun generateLambdaBody(lambdaInfo: ExpressionLambda, reifiedTypeParameters: ReifiedTypeParametersUsages): SMAPAndMethodNode
fun doCreateMethodNodeFromSource(
callableDescriptor: FunctionDescriptor,
jvmSignature: JvmMethodSignature,
callDefault: Boolean,
asmMethod: Method
): SMAPAndMethodNode
fun compileInlineFunction(jvmSignature: JvmMethodSignature): SMAPAndMethodNode
fun hasFinallyBlocks(): Boolean
fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(
finallyNode: MethodNode,
curFinallyDepth: Int
): BaseExpressionCodegen
fun generateFinallyBlocks(finallyNode: MethodNode, curFinallyDepth: Int, returnType: Type, afterReturnLabel: Label, target: Label?)
fun generateFinallyBlocksIfNeeded(codegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label, target: Label?)
val isCallInsideSameModuleAsCallee: Boolean
fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean
val isFinallyMarkerRequired: Boolean
fun isFinallyMarkerRequired(): Boolean
val compilationContextDescriptor: DeclarationDescriptor
val compilationContextFunctionDescriptor: FunctionDescriptor
fun isSuspendLambdaCapturedByOuterObjectOrLambda(name: String): Boolean
fun getContextLabels(): Map<String, Label?>
fun reportSuspensionPointInsideMonitor(stackTraceElement: String)
}
class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, override val callElement: KtElement) :
SourceCompilerForInline {
override val state = codegen.state
private var context by Delegates.notNull<CodegenContext<*>>()
private var additionalInnerClasses = mutableListOf<ClassDescriptor>()
override val lookupLocation = KotlinLookupLocation(callElement)
override val callElementText: String by lazy {
callElement.text
}
override val callsiteFile by lazy {
callElement.containingFile
}
override val contextKind
get () = context.contextKind
override val inlineCallSiteInfo: InlineCallSiteInfo
get() {
var context = codegen.getContext()
var parentCodegen = codegen.parentCodegen
while (context is InlineLambdaContext) {
val closureContext = context.getParentContext()
assert(closureContext is ClosureContext) { "Parent context of inline lambda should be closure context" }
assert(closureContext.parentContext is MethodContext) { "Closure context should appear in method context" }
context = closureContext.parentContext as MethodContext
assert(parentCodegen is FakeMemberCodegen) { "Parent codegen of inlined lambda should be FakeMemberCodegen" }
parentCodegen = (parentCodegen as FakeMemberCodegen).delegate
}
val signature = codegen.state.typeMapper.mapSignatureSkipGeneric(context.functionDescriptor, context.contextKind)
return InlineCallSiteInfo(
parentCodegen.className,
signature.asmMethod.name,
signature.asmMethod.descriptor,
compilationContextFunctionDescriptor.isInlineOrInsideInline(),
compilationContextFunctionDescriptor.isSuspend,
CodegenUtil.getLineNumberForElement(callElement, false) ?: 0
)
}
override val lazySourceMapper
get() = codegen.parentCodegen.orCreateSourceMapper
override fun generateLambdaBody(lambdaInfo: ExpressionLambda, reifiedTypeParameters: ReifiedTypeParametersUsages): SMAPAndMethodNode {
lambdaInfo as? PsiExpressionLambda ?: error("TODO")
val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor
val jvmMethodSignature = state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor)
val asmMethod = jvmMethodSignature.asmMethod
val methodNode = MethodNode(
Opcodes.API_VERSION, DescriptorAsmUtil.getMethodAsmFlags(invokeMethodDescriptor, OwnerKind.IMPLEMENTATION, state),
asmMethod.name, asmMethod.descriptor, null, null
)
val adapter = wrapWithMaxLocalCalc(methodNode)
val closureContext = when {
lambdaInfo.isPropertyReference ->
codegen.getContext().intoAnonymousClass(lambdaInfo.classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
invokeMethodDescriptor.isSuspend ->
codegen.getContext().intoCoroutineClosure(
getOrCreateJvmSuspendFunctionView(invokeMethodDescriptor, state), invokeMethodDescriptor, codegen, state.typeMapper
)
else -> codegen.getContext().intoClosure(invokeMethodDescriptor, codegen, state.typeMapper)
}
val context = closureContext.intoInlinedLambda(invokeMethodDescriptor, lambdaInfo.isCrossInline, lambdaInfo.isPropertyReference)
val smap = generateMethodBody(
adapter, invokeMethodDescriptor, context,
lambdaInfo.functionWithBodyOrCallableReference,
jvmMethodSignature, lambdaInfo
)
adapter.visitMaxs(-1, -1)
return SMAPAndMethodNode(methodNode, smap)
}
private fun generateMethodBody(
adapter: MethodVisitor,
descriptor: FunctionDescriptor,
context: MethodContext,
expression: KtExpression,
jvmMethodSignature: JvmMethodSignature,
lambdaInfo: PsiExpressionLambda?
): SMAP {
val isLambda = lambdaInfo != null
// Wrapping for preventing marking actual parent codegen as containing reified markers
val parentCodegen = FakeMemberCodegen(
codegen.parentCodegen, expression, context.parentContext as FieldOwnerContext<*>,
if (isLambda)
codegen.parentCodegen.className
else
state.typeMapper.mapImplementationOwner(descriptor).internalName,
if (isLambda) emptyList<ClassDescriptor>() else additionalInnerClasses,
isLambda
)
val strategy = when (expression) {
is KtCallableReferenceExpression -> {
val resolvedCall = expression.callableReference.getResolvedCallWithAssert(state.bindingContext)
val receiverKotlinType = JvmCodegenUtil.getBoundCallableReferenceReceiver(resolvedCall)?.type
val receiverType = receiverKotlinType?.let(state.typeMapper::mapType)
val boundReceiverJvmKotlinType = receiverType?.let { JvmKotlinType(receiverType, receiverKotlinType) }
if (isLambda && lambdaInfo!!.isPropertyReference) {
val asmType = state.typeMapper.mapClass(lambdaInfo.classDescriptor)
val info = lambdaInfo.propertyReferenceInfo
PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
true, info!!.getFunction, info.target, asmType,
boundReceiverJvmKotlinType,
lambdaInfo.functionWithBodyOrCallableReference, state, true
)
} else {
FunctionReferenceGenerationStrategy(state, descriptor, resolvedCall, boundReceiverJvmKotlinType, null, true)
}
}
is KtFunctionLiteral -> ClosureGenerationStrategy(state, expression as KtDeclarationWithBody)
else -> FunctionGenerationStrategy.FunctionDefault(state, expression as KtDeclarationWithBody)
}
FunctionCodegen.generateMethodBody(
adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen, state.jvmDefaultMode,
state.languageVersionSettings.isReleaseCoroutines()
)
if (isLambda) {
codegen.propagateChildReifiedTypeParametersUsages(parentCodegen.reifiedTypeParametersUsages)
}
return SMAP(parentCodegen.orCreateSourceMapper.resultMappings)
}
@Suppress("UNCHECKED_CAST")
private class FakeMemberCodegen(
internal val delegate: MemberCodegen<*>,
declaration: KtElement,
codegenContext: FieldOwnerContext<*>,
private val className: String,
private val parentAsInnerClasses: List<ClassDescriptor>,
private val isInlineLambdaCodegen: Boolean
) : MemberCodegen<KtPureElement>(delegate as MemberCodegen<KtPureElement>, declaration, codegenContext) {
override fun generateDeclaration() {
throw IllegalStateException()
}
override fun generateBody() {
throw IllegalStateException()
}
override fun generateKotlinMetadataAnnotation() {
throw IllegalStateException()
}
override fun getInlineNameGenerator(): NameGenerator {
return delegate.inlineNameGenerator
}
override //TODO: obtain name from context
fun getClassName(): String {
return className
}
override fun addParentsToInnerClassesIfNeeded(innerClasses: MutableCollection<ClassDescriptor>) {
if (isInlineLambdaCodegen) {
super.addParentsToInnerClassesIfNeeded(innerClasses)
} else {
innerClasses.addAll(parentAsInnerClasses)
}
}
override fun generateAssertField() {
delegate.generateAssertField()
}
}
override fun doCreateMethodNodeFromSource(
callableDescriptor: FunctionDescriptor,
jvmSignature: JvmMethodSignature,
callDefault: Boolean,
asmMethod: Method
): SMAPAndMethodNode {
val element = DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor)
if (!(element is KtNamedFunction || element is KtPropertyAccessor)) {
throw IllegalStateException("Couldn't find declaration for function $callableDescriptor")
}
val inliningFunction = element as KtDeclarationWithBody?
val node = MethodNode(
Opcodes.API_VERSION,
DescriptorAsmUtil.getMethodAsmFlags(callableDescriptor, context.contextKind, state) or if (callDefault) Opcodes.ACC_STATIC else 0,
asmMethod.name,
asmMethod.descriptor, null, null
)
//for maxLocals calculation
val maxCalcAdapter = wrapWithMaxLocalCalc(node)
val parentContext = context.parentContext ?: error("Context has no parent: " + context)
val methodContext = parentContext.intoFunction(callableDescriptor)
val smap = if (callDefault) {
val implementationOwner = state.typeMapper.mapImplementationOwner(callableDescriptor)
val parentCodegen = FakeMemberCodegen(
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
implementationOwner.internalName,
additionalInnerClasses,
false
)
if (element !is KtNamedFunction) {
throw IllegalStateException("Property accessors with default parameters not supported $callableDescriptor")
}
FunctionCodegen.generateDefaultImplBody(
methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
inliningFunction as KtNamedFunction?, parentCodegen, asmMethod
)
SMAP(parentCodegen.orCreateSourceMapper.resultMappings)
} else {
generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, null)
}
maxCalcAdapter.visitMaxs(-1, -1)
maxCalcAdapter.visitEnd()
return SMAPAndMethodNode(node, smap)
}
override fun hasFinallyBlocks() = codegen.hasFinallyBlocks()
override fun generateFinallyBlocksIfNeeded(codegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label, target: Label?) {
// TODO use the target label for non-local break/continue
require(codegen is ExpressionCodegen)
codegen.generateFinallyBlocksIfNeeded(returnType, null, afterReturnLabel)
}
override fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode: MethodNode, curFinallyDepth: Int) =
ExpressionCodegen(
finallyNode, codegen.frameMap, codegen.returnType,
codegen.getContext(), codegen.state, codegen.parentCodegen
).also {
it.addBlockStackElementsForNonLocalReturns(codegen.blockStackElements, curFinallyDepth)
}
override fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean {
return JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), codegen.state.outDirectory)
}
override fun isFinallyMarkerRequired(): Boolean = isFinallyMarkerRequired(codegen.getContext())
override val compilationContextDescriptor
get() = codegen.getContext().contextDescriptor
override val compilationContextFunctionDescriptor
get() = codegen.getContext().functionDescriptor
override fun getContextLabels(): Map<String, Label?> {
val context = codegen.getContext()
val parentContext = context.parentContext
val descriptor = if (parentContext is ClosureContext && parentContext.originalSuspendLambdaDescriptor != null) {
parentContext.originalSuspendLambdaDescriptor!!
} else context.contextDescriptor
val labels = InlineCodegen.getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor)
return labels.associateWith { null } // TODO add break/continue labels
}
fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) {
context = getContext(
functionDescriptor,
functionDescriptor,
state,
DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile,
additionalInnerClasses
)
}
override fun reportSuspensionPointInsideMonitor(stackTraceElement: String) {
org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor(callElement, state, stackTraceElement)
}
companion object {
fun getContext(
descriptor: DeclarationDescriptor,
innerDescriptor: DeclarationDescriptor,
state: GenerationState,
sourceFile: KtFile?,
additionalInners: MutableList<ClassDescriptor>
): CodegenContext<*> {
if (descriptor is PackageFragmentDescriptor) {
//no inners
return PackageContext(descriptor, state.rootContext, null, sourceFile)
}
val container = descriptor.containingDeclaration ?: error("No container for descriptor: $descriptor")
val containerContext = getContext(
container,
descriptor,
state,
sourceFile,
additionalInners
)
return when (descriptor) {
is ScriptDescriptor -> {
val earlierScripts = state.scriptSpecific.earlierScriptsForReplInterpreter
containerContext.intoScript(
descriptor,
earlierScripts ?: emptyList(),
descriptor as ClassDescriptor, state.typeMapper
)
}
is ClassDescriptor -> {
val kind =
when {
DescriptorUtils.isInterface(descriptor) &&
innerDescriptor !is ClassDescriptor &&
!innerDescriptor.isCallableMemberCompiledToJvmDefault(state.jvmDefaultMode) ->
OwnerKind.DEFAULT_IMPLS
else ->
OwnerKind.IMPLEMENTATION
}
additionalInners.addIfNotNull(
InnerClassConsumer.classForInnerClassRecord(descriptor, kind == OwnerKind.DEFAULT_IMPLS)
)
if (descriptor.isInlineClass()) {
containerContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state)
.intoClass(descriptor, OwnerKind.ERASED_INLINE_CLASS, state)
} else {
containerContext.intoClass(descriptor, kind, state)
}
}
is FunctionDescriptor -> {
containerContext.intoFunction(descriptor)
}
else -> {
throw IllegalStateException("Couldn't build context for $descriptor")
}
}
}
}
fun GenerationState.trackLookup(container: FqName, functionName: String, location: LocationInfo) {
val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER) ?: return
lookupTracker.record(
location.filePath,
if (lookupTracker.requiresPosition) location.position else Position.NO_POSITION,
container.asString(),
ScopeKind.CLASSIFIER,
functionName
)
}
fun DeclarationDescriptor.isInlineOrInsideInline(): Boolean =
if (this is FunctionDescriptor && isInline) true
else containingDeclaration?.isInlineOrInsideInline() == true
fun loadCompiledInlineFunction(
containerId: ClassId,
asmMethod: Method,
isSuspend: Boolean,
isMangled: Boolean,
state: GenerationState
): SMAPAndMethodNode {
val containerType = AsmUtil.asmTypeByClassId(containerId)
val resultInCache = state.inlineCache.methodNodeById.getOrPut(MethodId(containerType.descriptor, asmMethod)) {
val bytes = state.inlineCache.classBytes.getOrPut(containerType.internalName) {
findVirtualFile(state, containerId)?.contentsToByteArray()
?: throw IllegalStateException("Couldn't find declaration file for $containerId")
}
getMethodNode(containerType, bytes, asmMethod, isSuspend, isMangled)
}
return SMAPAndMethodNode(cloneMethodNode(resultInCache.node), resultInCache.classSMAP)
}
private fun getMethodNode(
owner: Type,
bytes: ByteArray,
method: Method,
isSuspend: Boolean,
isMangled: Boolean
): SMAPAndMethodNode {
getMethodNode(owner, bytes, method, isSuspend)?.let { return it }
if (isMangled) {
// Compatibility with old inline class ABI versions.
val dashIndex = method.name.indexOf('-')
val nameWithoutManglingSuffix = if (dashIndex > 0) method.name.substring(0, dashIndex) else method.name
if (nameWithoutManglingSuffix != method.name) {
getMethodNode(owner, bytes, Method(nameWithoutManglingSuffix, method.descriptor), isSuspend)?.let { return it }
}
getMethodNode(owner, bytes, Method("$nameWithoutManglingSuffix-impl", method.descriptor), isSuspend)?.let { return it }
}
throw IllegalStateException("couldn't find inline method $owner.$method")
}
// If an `inline suspend fun` has a state machine, it should have a `$$forInline` version without one.
private fun getMethodNode(owner: Type, bytes: ByteArray, method: Method, isSuspend: Boolean) =
(if (isSuspend) getMethodNode(bytes, owner, Method(method.name + FOR_INLINE_SUFFIX, method.descriptor)) else null)
?: getMethodNode(bytes, owner, method)

View File

@@ -6,18 +6,13 @@
package org.jetbrains.kotlin.codegen.inline.coroutines
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.coroutines.*
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.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.org.objectweb.asm.MethodVisitor
@@ -96,8 +91,8 @@ class CoroutineTransformer(
obtainClassBuilderForCoroutineState = { classBuilder },
reportSuspensionPointInsideMonitor = { sourceCompilerForInline.reportSuspensionPointInsideMonitor(it) },
// TODO: this linenumbers might not be correct and since they are used only for step-over, check them.
lineNumber = sourceCompilerForInline.inlineCallSiteInfo.lineNumber,
sourceFile = sourceCompilerForInline.callsiteFile?.name ?: "",
lineNumber = inliningContext.callSiteInfo.lineNumber,
sourceFile = inliningContext.callSiteInfo.file?.name ?: "",
languageVersionSettings = state.languageVersionSettings,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = classBuilder.thisName,
@@ -130,8 +125,8 @@ class CoroutineTransformer(
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! },
reportSuspensionPointInsideMonitor = { sourceCompilerForInline.reportSuspensionPointInsideMonitor(it) },
lineNumber = sourceCompilerForInline.inlineCallSiteInfo.lineNumber,
sourceFile = sourceCompilerForInline.callsiteFile?.name ?: "",
lineNumber = inliningContext.callSiteInfo.lineNumber,
sourceFile = inliningContext.callSiteInfo.file?.name ?: "",
languageVersionSettings = state.languageVersionSettings,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = classBuilder.thisName,
@@ -238,35 +233,6 @@ fun surroundInvokesWithSuspendMarkersIfNeeded(node: MethodNode) {
}
}
// We cannot find the lambda in captured parameters: it came from object outside of the our reach:
// this can happen when the lambda capture by non-transformed closure:
// inline fun inlineMe(crossinline c: suspend() -> Unit) = suspend { c() }
// inline fun inlineMe2(crossinline c: suspend() -> Unit) = suspend { inlineMe { c() }() }
// Suppose, we inline inlineMe into inlineMe2: the only knowledge we have about inlineMe$1 is captured receiver (this$0)
// Thus, transformed lambda from inlineMe, inlineMe3$$inlined$inlineMe2$1 contains the following bytecode
// ALOAD 0
// GETFIELD inlineMe2$1$invokeSuspend$$inlined$inlineMe$1.this$0 : LScratchKt$inlineMe2$1;
// GETFIELD inlineMe2$1.$c : Lkotlin/jvm/functions/Function1;
// Since inlineMe2's lambda is outside of reach of the inliner, find crossinline parameter from compilation context:
fun FieldInsnNode.isSuspendLambdaCapturedByOuterObjectOrLambda(inliningContext: InliningContext): Boolean {
var container: DeclarationDescriptor = inliningContext.root.sourceCompilerForInline.compilationContextFunctionDescriptor
while (container !is ClassDescriptor) {
container = container.containingDeclaration ?: return false
}
val bindingContext = inliningContext.state.bindingContext
var classDescriptor: ClassDescriptor? = container
while (classDescriptor != null) {
val closure = bindingContext[CodegenBinding.CLOSURE, classDescriptor] ?: return false
for ((param, value) in closure.captureVariables) {
if (param is ValueParameterDescriptor && value.fieldName == name) {
return param.type.isSuspendFunctionTypeOrSubtype
}
}
classDescriptor = closure.capturedOuterClassDescriptor
}
return false
}
// Interpreter, that keeps track of captured functional arguments
private class PossibleLambdaLoad(val insn: AbstractInsnNode) : BasicValue(AsmTypes.OBJECT_TYPE)

View File

@@ -16,20 +16,16 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.isNeedClassReificationMarker
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.*
import kotlin.math.max
private data class Condition(
val mask: Int, val constant: Int,
@@ -41,34 +37,15 @@ private data class Condition(
val varIndex = varInsNode?.`var` ?: 0
}
fun extractDefaultLambdaOffsetAndDescriptor(
jvmSignature: JvmMethodSignature,
functionDescriptor: FunctionDescriptor
): Map<Int, ValueParameterDescriptor> {
val valueParameters = jvmSignature.valueParameters
val containingDeclaration = functionDescriptor.containingDeclaration
val kind =
if (DescriptorUtils.isInterface(containingDeclaration)) OwnerKind.DEFAULT_IMPLS
else OwnerKind.getMemberOwnerKind(containingDeclaration)
val parameterOffsets = parameterOffsets(DescriptorAsmUtil.isStaticMethod(kind, functionDescriptor), valueParameters)
val valueParameterOffset = valueParameters.takeWhile { it.kind != JvmMethodParameterKind.VALUE }.size
class ExtractedDefaultLambda(val type: Type, val capturedArgs: Array<Type>, val offset: Int, val needReification: Boolean)
return functionDescriptor.valueParameters.filter {
InlineUtil.isInlineParameter(it) && it.declaresDefaultValue()
}.associateBy {
parameterOffsets[valueParameterOffset + it.index]
}
}
fun <T, R : DefaultLambda> expandMaskConditionsAndUpdateVariableNodes(
fun expandMaskConditionsAndUpdateVariableNodes(
node: MethodNode,
maskStartIndex: Int,
masks: List<Int>,
methodHandlerIndex: Int,
defaultLambdas: Map<Int, T>,
lambdaConstructor: (Type, Array<Type>, T, Int, Boolean) -> R
): List<R> {
validOffsets: Collection<Int>
): List<ExtractedDefaultLambda> {
fun isMaskIndex(varIndex: Int): Boolean {
return maskStartIndex <= varIndex && varIndex < maskStartIndex + masks.size
}
@@ -111,7 +88,8 @@ fun <T, R : DefaultLambda> expandMaskConditionsAndUpdateVariableNodes(
val toDelete = linkedSetOf<AbstractInsnNode>()
val toInsert = arrayListOf<Pair<AbstractInsnNode, AbstractInsnNode>>()
val defaultLambdasInfo = extractDefaultLambdasInfo(conditions, defaultLambdas, toDelete, toInsert, lambdaConstructor)
val extractable = conditions.filter { it.expandNotDelete && it.varIndex in validOffsets }
val defaultLambdasInfo = extractDefaultLambdasInfo(extractable, toDelete, toInsert)
val indexToVarNode = node.localVariables?.filter { it.index < maskStartIndex }?.associateBy { it.index } ?: emptyMap()
conditions.forEach {
@@ -131,7 +109,7 @@ fun <T, R : DefaultLambda> expandMaskConditionsAndUpdateVariableNodes(
}
node.localVariables.removeIf {
(it.start in toDelete && it.end in toDelete) || defaultLambdas.contains(it.index)
(it.start in toDelete && it.end in toDelete) || validOffsets.contains(it.index)
}
node.remove(toDelete)
@@ -139,16 +117,12 @@ fun <T, R : DefaultLambda> expandMaskConditionsAndUpdateVariableNodes(
return defaultLambdasInfo
}
private fun <T, R : DefaultLambda> extractDefaultLambdasInfo(
private fun extractDefaultLambdasInfo(
conditions: List<Condition>,
defaultLambdas: Map<Int, T>,
toDelete: MutableCollection<AbstractInsnNode>,
toInsert: MutableList<Pair<AbstractInsnNode, AbstractInsnNode>>,
lambdaConstructor: (Type, Array<Type>, T, Int, Boolean) -> R
): List<R> {
val defaultLambdaConditions = conditions.filter { it.expandNotDelete && defaultLambdas.contains(it.varIndex) }
return defaultLambdaConditions.map {
toInsert: MutableList<Pair<AbstractInsnNode, AbstractInsnNode>>
): List<ExtractedDefaultLambda> {
return conditions.map {
val varAssignmentInstruction = it.varInsNode!!
var instanceInstuction = varAssignmentInstruction.previous
if (instanceInstuction is TypeInsnNode && instanceInstuction.opcode == Opcodes.CHECKCAST) {
@@ -190,7 +164,7 @@ private fun <T, R : DefaultLambda> extractDefaultLambdasInfo(
toInsert.add(varAssignmentInstruction to defaultLambdaFakeCallStub(argTypes, it.varIndex))
lambdaConstructor(owner, argTypes, defaultLambdas[it.varIndex]!!, it.varIndex, needReification)
ExtractedDefaultLambda(owner, argTypes, it.varIndex, needReification)
}
}
@@ -205,3 +179,68 @@ private fun defaultLambdaFakeCallStub(args: Array<Type>, lambdaOffset: Int): Met
false
)
}
fun loadDefaultLambdaBody(classBytes: ByteArray, classType: Type, isPropertyReference: Boolean): SMAPAndMethodNode {
// In general we can't know what the correct unboxed `invoke` is, and what Kotlin types its arguments have,
// as the type of this object may be any subtype of the parameter's type. All we know is that Function<N>
// has to have a `invoke` that takes `Object`s and returns an `Object`; everything else needs to be figured
// out from its contents. TODO: for > 22 arguments, the only argument is an array. `MethodInliner` can't do that.
val invokeName = if (isPropertyReference) OperatorNameConventions.GET.asString() else OperatorNameConventions.INVOKE.asString()
val invokeNode = getMethodNode(classBytes, classType) {
it.name == invokeName && it.returnType == AsmTypes.OBJECT_TYPE && it.argumentTypes.all { arg -> arg == AsmTypes.OBJECT_TYPE }
} ?: error("can't find erased invoke '$invokeName(Object...): Object' in default lambda '${classType.internalName}'")
return if (invokeNode.node.access.and(Opcodes.ACC_BRIDGE) == 0)
invokeNode
else
invokeNode.node.inlineBridge(classBytes, classType)
}
private fun MethodNode.inlineBridge(classBytes: ByteArray, classType: Type): SMAPAndMethodNode {
// If the erased invoke is a bridge, we need to locate the unboxed invoke and inline it. As mentioned above,
// we don't know what the Kotlin types of its arguments/returned value are, so we can't generate our own
// boxing/unboxing code; luckily, the bridge already has that.
val invokeInsn = instructions.singleOrNull { it is MethodInsnNode && it.owner == classType.internalName } as MethodInsnNode?
?: error("no single invoke of method on this in '${name}${desc}' of default lambda '${classType.internalName}'")
val targetMethod = Method(invokeInsn.name, invokeInsn.desc)
val target = getMethodNode(classBytes, classType, targetMethod)
?: error("can't find non-bridge invoke '$targetMethod' in default lambda '${classType.internalName}")
// Store unboxed/casted arguments in the correct variable slots
val targetArgs = targetMethod.argumentTypes
val targetArgsSize = targetArgs.sumOf { it.size } + if (target.node.access.and(Opcodes.ACC_STATIC) == 0) 1 else 0
var offset = targetArgsSize
for (type in targetArgs.reversed()) {
offset -= type.size
instructions.insertBefore(invokeInsn, VarInsnNode(type.getOpcode(Opcodes.ISTORE), offset))
}
if (target.node.access.and(Opcodes.ACC_STATIC) == 0) {
instructions.insertBefore(invokeInsn, InsnNode(Opcodes.POP)) // this
}
// Remap returns and ranges for arguments' LVT entries
val invokeLabel = LabelNode()
val returnLabel = LabelNode()
instructions.insertBefore(invokeInsn, invokeLabel)
instructions.insert(invokeInsn, returnLabel)
for (insn in target.node.instructions) {
if (insn.opcode in Opcodes.IRETURN..Opcodes.RETURN) {
target.node.instructions.set(insn, JumpInsnNode(Opcodes.GOTO, returnLabel))
}
}
for (local in target.node.localVariables) {
if (local.index < targetArgsSize) {
local.start = invokeLabel
local.end = returnLabel
}
}
// Insert contents of the method into the bridge
instructions.filterIsInstance<LineNumberNode>().forEach { instructions.remove(it) } // those are not meaningful
instructions.insertBefore(invokeInsn, target.node.instructions)
instructions.remove(invokeInsn)
localVariables = target.node.localVariables
tryCatchBlocks = target.node.tryCatchBlocks
maxLocals = max(maxLocals, target.node.maxLocals)
maxStack = max(maxStack, target.node.maxStack)
return SMAPAndMethodNode(this, target.classSMAP)
}

View File

@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.util.Printer
import org.jetbrains.org.objectweb.asm.util.Textifier
@@ -84,40 +85,18 @@ private const val INLINE_MARKER_AFTER_INLINE_SUSPEND_ID = 7
private const val INLINE_MARKER_BEFORE_UNBOX_INLINE_CLASS = 8
private const val INLINE_MARKER_AFTER_UNBOX_INLINE_CLASS = 9
internal fun getMethodNode(
classData: ByteArray,
methodName: String,
methodDescriptor: String,
classType: Type,
signatureAmbiguity: Boolean = false
): SMAPAndMethodNode? {
val cr = ClassReader(classData)
internal inline fun getMethodNode(classData: ByteArray, classType: Type, crossinline match: (Method) -> Boolean): SMAPAndMethodNode? {
var node: MethodNode? = null
val debugInfo = arrayOfNulls<String>(2)
cr.accept(object : ClassVisitor(Opcodes.API_VERSION) {
var sourceFile: String? = null
var sourceMap: String? = null
ClassReader(classData).accept(object : ClassVisitor(Opcodes.API_VERSION) {
override fun visitSource(source: String?, debug: String?) {
super.visitSource(source, debug)
debugInfo[0] = source
debugInfo[1] = debug
sourceFile = source
sourceMap = debug
}
override fun visitMethod(
access: Int,
name: String,
desc: String,
signature: String?,
exceptions: Array<String>?
): MethodVisitor? {
if (methodName != name || (signatureAmbiguity && access.and(Opcodes.ACC_SYNTHETIC) != 0)) return null
if (methodDescriptor != desc) {
val sameNumberOfParameters = Type.getArgumentTypes(methodDescriptor).size == Type.getArgumentTypes(desc).size
if (!signatureAmbiguity || !sameNumberOfParameters) {
return null
}
}
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
if (!match(Method(name, desc))) return null
node?.let { existing ->
throw AssertionError("Can't find proper '$name' method for inline: ambiguity between '${existing.name + existing.desc}' and '${name + desc}'")
}
@@ -126,15 +105,15 @@ internal fun getMethodNode(
}
}, ClassReader.SKIP_FRAMES or if (GENERATE_SMAP) 0 else ClassReader.SKIP_DEBUG)
if (node == null) {
return null
return node?.let{
val (first, last) = listOfNotNull(it).lineNumberRange()
SMAPAndMethodNode(it, SMAPParser.parseOrCreateDefault(sourceMap, sourceFile, classType.internalName, first, last))
}
val (first, last) = listOfNotNull(node).lineNumberRange()
val smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classType.internalName, first, last)
return SMAPAndMethodNode(node!!, smap)
}
internal fun getMethodNode(classData: ByteArray, classType: Type, method: Method): SMAPAndMethodNode? =
getMethodNode(classData, classType) { it == method }
internal fun Collection<MethodNode>.lineNumberRange(): Pair<Int, Int> {
var minLine = Int.MAX_VALUE
var maxLine = Int.MIN_VALUE
@@ -347,8 +326,42 @@ internal val AbstractInsnNode?.insnText: String
return sw.toString().trim()
}
fun AbstractInsnNode?.insnText(insnList: InsnList): String {
if (this == null) return "<null>"
fun AbstractInsnNode.indexOf() =
insnList.indexOf(this)
fun LabelNode.labelText() =
"L#${this.indexOf()}"
return when (this) {
is LabelNode ->
labelText()
is JumpInsnNode ->
"$insnOpcodeText ${label.labelText()}"
is LookupSwitchInsnNode ->
"$insnOpcodeText " +
this.keys.zip(this.labels).joinToString(prefix = "[", postfix = "]") { (key, label) -> "$key:${label.labelText()}" }
is TableSwitchInsnNode ->
"$insnOpcodeText " +
(min..max).zip(this.labels).joinToString(prefix = "[", postfix = "]") { (key, label) -> "$key:${label.labelText()}" }
else ->
insnText
}
}
internal val AbstractInsnNode?.insnOpcodeText: String
get() = if (this == null) "null" else Printer.OPCODES[opcode]
get() = when (this) {
null -> "null"
is LabelNode -> "LABEL"
is LineNumberNode -> "LINENUMBER"
is FrameNode -> "FRAME"
else -> Printer.OPCODES[opcode]
}
internal fun TryCatchBlockNode.text(insns: InsnList): String =
"[${insns.indexOf(start)} .. ${insns.indexOf(end)} -> ${insns.indexOf(handler)}]"
internal fun loadClassBytesByInternalName(state: GenerationState, internalName: String): ByteArray {
//try to find just compiled classes then in dependencies

View File

@@ -14,8 +14,9 @@ import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForCoroutineConte
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
import org.jetbrains.kotlin.codegen.isBuiltinAlwaysEnabledAssert
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.resolve.calls.checkers.TypeOfChecker
@@ -26,31 +27,42 @@ import org.jetbrains.kotlin.types.model.TypeParameterMarker
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.commons.Method
import org.jetbrains.org.objectweb.asm.tree.MethodNode
internal fun generateInlineIntrinsic(
state: GenerationState,
descriptor: FunctionDescriptor,
typeParameters: List<TypeParameterMarker>?,
typeSystem: TypeSystemCommonBackendContext
): MethodNode? {
val languageVersionSettings = state.languageVersionSettings
return when {
isSpecialEnumMethod(descriptor) ->
createSpecialEnumMethodBody(descriptor.name.asString(), typeParameters!!.single(), typeSystem)
TypeOfChecker.isTypeOf(descriptor) ->
typeSystem.createTypeOfMethodBody(typeParameters!!.single())
fun generateInlineIntrinsicForIr(languageVersionSettings: LanguageVersionSettings, 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)
else -> null
}?.let { SMAPAndMethodNode(it, SMAP(listOf())) }
internal fun generateInlineIntrinsic(
languageVersionSettings: LanguageVersionSettings,
descriptor: FunctionDescriptor,
asmMethod: Method,
typeSystem: TypeSystemCommonBackendContext
): SMAPAndMethodNode? {
return generateInlineIntrinsicForIr(languageVersionSettings, descriptor) ?: when {
isSpecialEnumMethod(descriptor) ->
createSpecialEnumMethodBody(descriptor.name.asString(), descriptor.original.typeParameters.single(), typeSystem)
TypeOfChecker.isTypeOf(descriptor) ->
typeSystem.createTypeOfMethodBody(descriptor.original.typeParameters.single())
descriptor.isBuiltinAlwaysEnabledAssert() ->
createMethodNodeForAlwaysEnabledAssert(descriptor)
descriptor is FictitiousArrayConstructor ->
IntrinsicArrayConstructors.generateArrayConstructorBody(asmMethod)
IntrinsicArrayConstructors.isArrayOf(descriptor) ->
IntrinsicArrayConstructors.generateArrayOfBody(asmMethod)
IntrinsicArrayConstructors.isEmptyArray(descriptor) ->
IntrinsicArrayConstructors.generateEmptyArrayBody(asmMethod)
else -> null
}
}?.let { SMAPAndMethodNode(it, SMAP(listOf())) }
}
private fun isSpecialEnumMethod(descriptor: FunctionDescriptor): Boolean {

View File

@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
@@ -37,15 +38,15 @@ private fun TypeSystemCommonBackendContext.putTypeOfReifiedTypeParameter(
v.aconst(null)
}
internal fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateTypeOf(
fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateTypeOf(
v: InstructionAdapter, type: KT, intrinsicsSupport: ReifiedTypeInliner.IntrinsicsSupport<KT>
) {
val typeParameter = type.typeConstructor().getTypeParameterClassifier()
if (typeParameter != null) {
if (!doesTypeContainTypeParametersWithRecursiveBounds(type)) {
throw UnsupportedOperationException(
"Non-reified type parameters with recursive bounds are not supported yet: ${typeParameter.getName()}"
)
intrinsicsSupport.reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameter.getName())
v.aconst(null)
return
}
generateNonReifiedTypeParameter(v, typeParameter, intrinsicsSupport)
@@ -89,6 +90,27 @@ internal fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateType
}
v.invokestatic(REFLECTION, methodName, signature, false)
if (intrinsicsSupport.toKotlinType(type).isSuspendFunctionType) {
intrinsicsSupport.reportSuspendTypeUnsupported()
}
if (intrinsicsSupport.state.stableTypeOf) {
if (intrinsicsSupport.isMutableCollectionType(type)) {
v.invokestatic(REFLECTION, "mutableCollectionType", Type.getMethodDescriptor(K_TYPE, K_TYPE), false)
} else if (type.typeConstructor().isNothingConstructor()) {
v.invokestatic(REFLECTION, "nothingType", Type.getMethodDescriptor(K_TYPE, K_TYPE), false)
}
if (type.isFlexible()) {
// If this is a flexible type, we've just generated its lower bound and have it on the stack.
// Let's generate the upper bound now and call the method that takes lower and upper bound and constructs a flexible KType.
@Suppress("UNCHECKED_CAST")
generateTypeOf(v, type.upperBoundIfFlexible() as KT, intrinsicsSupport)
v.invokestatic(REFLECTION, "platformType", Type.getMethodDescriptor(K_TYPE, K_TYPE, K_TYPE), false)
}
}
}
private fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateNonReifiedTypeParameter(
@@ -103,7 +125,7 @@ private fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateNonRe
TypeVariance.OUT -> KVariance.OUT
}
v.getstatic(K_VARIANCE.internalName, variance.name, K_VARIANCE.descriptor)
v.aconst(typeParameter.isReified())
v.iconst(if (typeParameter.isReified()) 1 else 0)
v.invokestatic(
REFLECTION, "typeParameter",
Type.getMethodDescriptor(K_TYPE_PARAMETER, OBJECT_TYPE, JAVA_STRING_TYPE, K_VARIANCE, Type.BOOLEAN_TYPE),
@@ -119,11 +141,11 @@ private fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateNonRe
if (bounds.size == 1) {
generateTypeOf(v, bounds.single(), intrinsicsSupport)
} else {
v.aconst(bounds.size)
v.iconst(bounds.size)
v.newarray(K_TYPE)
for ((i, bound) in bounds.withIndex()) {
v.dup()
v.aconst(i)
v.iconst(i)
generateTypeOf(v, bound, intrinsicsSupport)
v.astore(K_TYPE)
}

View File

@@ -16,10 +16,14 @@
package org.jetbrains.kotlin.codegen.intrinsics
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.inline.ReificationArgument
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.org.objectweb.asm.Label
@@ -30,6 +34,15 @@ import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.MethodNode
internal object IntrinsicArrayConstructors {
fun isArrayOf(descriptor: FunctionDescriptor): Boolean =
descriptor.name.asString() == "arrayOf" && descriptor.containingDeclaration.isBuiltInsPackage
fun isEmptyArray(descriptor: FunctionDescriptor): Boolean =
descriptor.name.asString() == "emptyArray" && descriptor.containingDeclaration.isBuiltInsPackage
private val DeclarationDescriptor.isBuiltInsPackage: Boolean
get() = this is PackageFragmentDescriptor && fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME
fun generateArrayConstructorBody(method: Method): MethodNode {
val node = MethodNode(
Opcodes.ASM6, Opcodes.ACC_PUBLIC or Opcodes.ACC_STATIC or Opcodes.ACC_FINAL, method.name, method.descriptor, null, null

View File

@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
import org.jetbrains.kotlin.codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter
import org.jetbrains.kotlin.psi.KtClassLiteralExpression
import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall

View File

@@ -34,11 +34,26 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
if (!methodNode.hasOptimizableConditions()) {
return
}
do {
val changes = ConstantConditionsOptimization(internalClassName, methodNode).run()
} while (changes)
}
private fun MethodNode.hasOptimizableConditions(): Boolean {
val insns = instructions.toArray()
return insns.any { it.isIntJump() } && insns.any { it.isIntConst() }
}
private fun AbstractInsnNode.isIntConst() =
opcode in Opcodes.ICONST_M1..Opcodes.ICONST_5 || opcode == Opcodes.BIPUSH || opcode == Opcodes.SIPUSH ||
(opcode == Opcodes.LDC && this is LdcInsnNode && cst is Int)
private fun AbstractInsnNode.isIntJump() =
opcode in Opcodes.IFEQ..Opcodes.IFLE || opcode in Opcodes.IF_ICMPEQ..Opcodes.IF_ICMPLE
private class ConstantConditionsOptimization(val internalClassName: String, val methodNode: MethodNode) {
fun run(): Boolean {
val actions = collectRewriteActions()

View File

@@ -72,18 +72,30 @@ class OptimizationMethodVisitor(
}
companion object {
private val MEMORY_LIMIT_BY_METHOD_MB = 50
private const val MEMORY_LIMIT_BY_METHOD_MB = 50
private const val TRY_CATCH_BLOCKS_SOFT_LIMIT = 16
fun canBeOptimized(node: MethodNode): Boolean {
val totalFramesSizeMb = node.instructions.size() * (node.maxLocals + node.maxStack) / (1024 * 1024)
return totalFramesSizeMb < MEMORY_LIMIT_BY_METHOD_MB
if (node.tryCatchBlocks.size > TRY_CATCH_BLOCKS_SOFT_LIMIT) {
if (getTotalFramesWeight(getTotalTcbSize(node), node) > MEMORY_LIMIT_BY_METHOD_MB)
return false
}
return getTotalFramesWeight(node.instructions.size(), node) < MEMORY_LIMIT_BY_METHOD_MB
}
fun canBeOptimizedUsingSourceInterpreter(node: MethodNode): Boolean {
val frameSize = node.maxLocals + node.maxStack
val methodSize = node.instructions.size().toLong()
val totalFramesSizeMb = methodSize * methodSize * frameSize / (1024 * 1024)
return totalFramesSizeMb < MEMORY_LIMIT_BY_METHOD_MB
val methodSize = node.instructions.size()
if (node.tryCatchBlocks.size > TRY_CATCH_BLOCKS_SOFT_LIMIT) {
if (getTotalFramesWeight(getTotalTcbSize(node) * methodSize, node) > MEMORY_LIMIT_BY_METHOD_MB)
return false
}
return getTotalFramesWeight(methodSize * methodSize, node) < MEMORY_LIMIT_BY_METHOD_MB
}
private fun getTotalFramesWeight(size: Int, node: MethodNode) =
size.toLong() * (node.maxLocals + node.maxStack) / (1024 * 1024)
private fun getTotalTcbSize(node: MethodNode) =
node.tryCatchBlocks.sumOf { node.instructions.indexOf(it.end) - node.instructions.indexOf(it.start) }
}
}

View File

@@ -56,7 +56,7 @@ class TaintedBoxedValue(private val boxedBasicValue: CleanBoxedValue) : BoxedBas
class BoxedValueDescriptor(
private val boxedType: Type,
boxedType: Type,
val boxingInsn: AbstractInsnNode,
val progressionIterator: ProgressionIteratorBasicValue?,
val generationState: GenerationState

View File

@@ -17,13 +17,16 @@
package org.jetbrains.kotlin.codegen.optimization.boxing
import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.isLoadOperation
import org.jetbrains.kotlin.codegen.optimization.fixStack.peekWords
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.Analyzer
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
@@ -52,7 +55,7 @@ class PopBackwardPropagationTransformer : MethodTransformer() {
private val dontTouchInsnIndices = BitSet(insns.size)
fun transform() {
val frames = Analyzer(HazardsTrackingInterpreter()).analyze("fake", methodNode)
val frames = FastMethodAnalyzer("fake", methodNode, HazardsTrackingInterpreter()).analyze()
for ((i, insn) in insns.withIndex()) {
val frame = frames[i] ?: continue
when (insn.opcode) {

View File

@@ -38,6 +38,10 @@ import java.util.*
class RedundantBoxingMethodTransformer(private val generationState: GenerationState) : MethodTransformer() {
override fun transform(internalClassName: String, node: MethodNode) {
val insns = node.instructions.toArray()
if (insns.none { it.isBoxing(generationState) || it.isMethodInsnWith(Opcodes.INVOKEINTERFACE) { name == "next" } })
return
val interpreter = RedundantBoxingInterpreter(node.instructions, generationState)
val frames = analyze(internalClassName, node, interpreter)

View File

@@ -5,46 +5,160 @@
package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnList
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import gnu.trove.TIntHashSet
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.*
class ControlFlowGraph private constructor(private val insns: InsnList) {
private val edges: Array<MutableList<Int>> = Array(insns.size()) { arrayListOf<Int>() }
private val backwardEdges: Array<MutableList<Int>> = Array(insns.size()) { arrayListOf<Int>() }
private val successors: Array<MutableList<Int>> = Array(insns.size()) { ArrayList(2) }
private val predecessors: Array<MutableList<Int>> = Array(insns.size()) { ArrayList(2) }
fun getSuccessorsIndices(insn: AbstractInsnNode): List<Int> = getSuccessorsIndices(insns.indexOf(insn))
fun getSuccessorsIndices(index: Int): List<Int> = edges[index]
fun getSuccessorsIndices(index: Int): List<Int> = successors[index]
fun getPredecessorsIndices(insn: AbstractInsnNode): List<Int> = getPredecessorsIndices(insns.indexOf(insn))
fun getPredecessorsIndices(index: Int): List<Int> = backwardEdges[index]
fun getPredecessorsIndices(index: Int): List<Int> = predecessors[index]
private class Builder(
private val method: MethodNode,
private val followExceptions: Boolean
) {
private val instructions = method.instructions
private val nInsns = instructions.size()
private val handlers: Array<MutableList<TryCatchBlockNode>?> = arrayOfNulls(nInsns)
private val queued = BooleanArray(nInsns)
private val queue = IntArray(nInsns)
private var top = 0
private val predecessors = Array(nInsns) { TIntHashSet() }
private val AbstractInsnNode.indexOf get() = instructions.indexOf(this)
fun build(): ControlFlowGraph {
val graph = ControlFlowGraph(method.instructions)
if (nInsns == 0) return graph
checkAssertions()
computeExceptionHandlersForEachInsn()
initControlFlowAnalysis()
traverseCfg()
for ((i, preds) in predecessors.withIndex()) {
for (pred in preds.toArray()) {
graph.predecessors[i].add(pred)
graph.successors[pred].add(i)
}
}
return graph
}
private fun traverseCfg() {
while (top > 0) {
val insn = queue[--top]
val insnNode = method.instructions[insn]
val insnOpcode = insnNode.opcode
when (insnNode.type) {
AbstractInsnNode.LABEL, AbstractInsnNode.LINE, AbstractInsnNode.FRAME ->
visitOpInsn(insn)
AbstractInsnNode.JUMP_INSN ->
visitJumpInsnNode(insnNode as JumpInsnNode, insn, insnOpcode)
AbstractInsnNode.LOOKUPSWITCH_INSN ->
visitLookupSwitchInsnNode(insn, insnNode as LookupSwitchInsnNode)
AbstractInsnNode.TABLESWITCH_INSN ->
visitTableSwitchInsnNode(insn, insnNode as TableSwitchInsnNode)
else -> {
if (insnOpcode != Opcodes.ATHROW && (insnOpcode < Opcodes.IRETURN || insnOpcode > Opcodes.RETURN)) {
visitOpInsn(insn)
}
}
}
handlers[insn]?.forEach { tcb ->
visitExceptionEdge(insn, tcb.handler.indexOf)
}
}
}
private fun checkAssertions() {
if (instructions.any { it.opcode == Opcodes.JSR || it.opcode == Opcodes.RET })
throw AssertionError("Subroutines are deprecated since Java 6")
}
private fun visitOpInsn(insn: Int) {
visitEdge(insn, insn + 1)
}
private fun visitTableSwitchInsnNode(insn: Int, insnNode: TableSwitchInsnNode) {
var jump = insnNode.dflt.indexOf
visitEdge(insn, jump)
for (label in insnNode.labels) {
jump = label.indexOf
visitEdge(insn, jump)
}
}
private fun visitLookupSwitchInsnNode(insn: Int, insnNode: LookupSwitchInsnNode) {
var jump = insnNode.dflt.indexOf
visitEdge(insn, jump)
for (label in insnNode.labels) {
jump = label.indexOf
visitEdge(insn, jump)
}
}
private fun visitJumpInsnNode(insnNode: JumpInsnNode, insn: Int, insnOpcode: Int) {
if (insnOpcode != Opcodes.GOTO && insnOpcode != Opcodes.JSR) {
visitEdge(insn, insn + 1)
}
val jump = insnNode.label.indexOf
visitEdge(insn, jump)
}
private fun initControlFlowAnalysis() {
queued[0] = true
queue[top++] = 0
}
private fun computeExceptionHandlersForEachInsn() {
for (tcb in method.tryCatchBlocks) {
val begin = tcb.start.indexOf
val end = tcb.end.indexOf
for (j in begin until end) {
val insnHandlers = handlers[j]
?: ArrayList<TryCatchBlockNode>().also { handlers[j] = it }
insnHandlers.add(tcb)
}
}
}
private fun visitExceptionEdge(from: Int, to: Int) {
if (followExceptions) {
predecessors[to].add(from)
}
enqueue(to)
}
private fun visitEdge(from: Int, to: Int) {
predecessors[to].add(from)
enqueue(to)
}
private fun enqueue(insn: Int) {
if (!queued[insn]) {
queued[insn] = true
queue[top++] = insn
}
}
}
companion object {
@JvmStatic
fun build(node: MethodNode, followExceptions: Boolean = true): ControlFlowGraph {
val graph = ControlFlowGraph(node.instructions)
fun addEdge(from: Int, to: Int) {
graph.edges[from].add(to)
graph.backwardEdges[to].add(from)
}
object : MethodAnalyzer<BasicValue>("fake", node, OptimizationBasicInterpreter()) {
override fun visitControlFlowEdge(insn: Int, successor: Int): Boolean {
addEdge(insn, successor)
return true
}
override fun visitControlFlowExceptionEdge(insn: Int, successor: Int): Boolean {
if (followExceptions) {
addEdge(insn, successor)
}
return true
}
}.analyze()
return graph
return Builder(node, followExceptions).build()
}
}
}

View File

@@ -24,6 +24,6 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Value
class CustomFramesMethodAnalyzer<V : Value>(
owner: String, method: MethodNode, interpreter: Interpreter<V>,
private val frameFactory: (Int, Int) -> Frame<V>
) : MethodAnalyzer<V>(owner, method, interpreter) {
) : FastMethodAnalyzer<V>(owner, method, interpreter) {
override fun newFrame(nLocals: Int, nStack: Int) = frameFactory(nLocals, nStack)
}

View File

@@ -0,0 +1,374 @@
/*
* 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.
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.kotlin.codegen.inline.insnOpcodeText
import org.jetbrains.kotlin.codegen.inline.insnText
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
/**
* @see org.jetbrains.kotlin.codegen.optimization.fixStack.FastStackAnalyzer
*/
@Suppress("DuplicatedCode")
open class FastMethodAnalyzer<V : Value>(
private val owner: String,
val method: MethodNode,
private val interpreter: Interpreter<V>
) {
private val insnsArray = method.instructions.toArray()
private val nInsns = method.instructions.size()
// Single Predecessor Block (SPB) is a continuous sequence of instructions { I1, ... In } such that
// if I=insns[i] and J=insns[i+1] both belong to SPB,
// then I is a single immediate predecessor of J in a complete method control flow graph
// (including exception edges).
//
// Note that classic basic blocks are SPBs, but the opposite is not true:
// SPBs have single entry point, but can have multiple exit points
// (which lead to instructions not belonging to the given SPB).
// Example:
// aload 1
// dup
// ifnull LA
// invokevirtual foo()
// dup
// ifnull LB
// invokevirtual bar()
// goto LC
// is SPB (but not a basic block).
//
// For each J=insns[i+1] such that I=insns[i] belongs to the same SPB,
// data flow transfer function
// Execute( J, Merge( { Out(K) | K <- Pred(J) } ) )
// is effectively
// Execute( J, Out(I) ) )
// so, we don't need to merge frames for such I->J edges.
private val singlePredBlock = IntArray(nInsns)
val frames: Array<Frame<V>?> = arrayOfNulls(nInsns)
private val handlers: Array<MutableList<TryCatchBlockNode>?> = arrayOfNulls(nInsns)
private val queued = BooleanArray(nInsns)
private val queue = IntArray(nInsns)
private var top = 0
protected open fun newFrame(nLocals: Int, nStack: Int): Frame<V> =
Frame(nLocals, nStack)
fun analyze(): Array<Frame<V>?> {
if (nInsns == 0) return frames
checkAssertions()
computeExceptionHandlersForEachInsn(method)
initSinglePredBlocks()
val current = newFrame(method.maxLocals, method.maxStack)
val handler = newFrame(method.maxLocals, method.maxStack)
initControlFlowAnalysis(current, method, owner)
while (top > 0) {
val insn = queue[--top]
val f = frames[insn]!!
queued[insn] = false
val insnNode = method.instructions[insn]
try {
val insnOpcode = insnNode.opcode
val insnType = insnNode.type
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
visitNopInsn(f, insn)
} else {
current.init(f).execute(insnNode, interpreter)
when {
insnNode is JumpInsnNode ->
visitJumpInsnNode(insnNode, current, insn, insnOpcode)
insnNode is LookupSwitchInsnNode ->
visitLookupSwitchInsnNode(insnNode, current, insn)
insnNode is TableSwitchInsnNode ->
visitTableSwitchInsnNode(insnNode, current, insn)
insnOpcode != Opcodes.ATHROW && (insnOpcode < Opcodes.IRETURN || insnOpcode > Opcodes.RETURN) ->
visitOpInsn(current, insn)
else -> {
}
}
}
handlers[insn]?.forEach { tcb ->
val exnType = Type.getObjectType(tcb.type ?: "java/lang/Throwable")
val jump = tcb.handler.indexOf()
handler.init(f)
handler.clearStack()
handler.push(interpreter.newValue(exnType))
mergeControlFlowEdge(insn, jump, handler)
}
} catch (e: AnalyzerException) {
throw AnalyzerException(e.node, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
} catch (e: Exception) {
throw AnalyzerException(insnNode, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
}
}
return frames
}
private fun AbstractInsnNode.indexOf() =
method.instructions.indexOf(this)
private fun initSinglePredBlocks() {
markSinglePredBlockEntries()
markSinglePredBlockBodies()
}
private fun markSinglePredBlockEntries() {
// Method entry point is SPB entry point.
var blockId = 0
singlePredBlock[0] = ++blockId
// Every jump target is SPB entry point.
for (insn in insnsArray) {
when (insn) {
is JumpInsnNode -> {
val labelIndex = insn.label.indexOf()
if (singlePredBlock[labelIndex] == 0) {
singlePredBlock[labelIndex] = ++blockId
}
}
is LookupSwitchInsnNode -> {
insn.dflt?.let { dfltLabel ->
val dfltIndex = dfltLabel.indexOf()
if (singlePredBlock[dfltIndex] == 0) {
singlePredBlock[dfltIndex] = ++blockId
}
}
for (label in insn.labels) {
val labelIndex = label.indexOf()
if (singlePredBlock[labelIndex] == 0) {
singlePredBlock[labelIndex] = ++blockId
}
}
}
is TableSwitchInsnNode -> {
insn.dflt?.let { dfltLabel ->
val dfltIndex = dfltLabel.indexOf()
if (singlePredBlock[dfltIndex] == 0) {
singlePredBlock[dfltIndex] = ++blockId
}
}
for (label in insn.labels) {
val labelIndex = label.indexOf()
if (singlePredBlock[labelIndex] == 0) {
singlePredBlock[labelIndex] = ++blockId
}
}
}
}
}
// Every try-catch block handler entry point is SPB entry point
for (tcb in method.tryCatchBlocks) {
val handlerIndex = tcb.handler.indexOf()
if (singlePredBlock[handlerIndex] == 0) {
singlePredBlock[handlerIndex] = ++blockId
}
}
}
private fun markSinglePredBlockBodies() {
var current = 0
for ((i, insn) in insnsArray.withIndex()) {
if (singlePredBlock[i] == 0) {
singlePredBlock[i] = current
} else {
// Entered a new SPB.
current = singlePredBlock[i]
}
// GOTO, ATHROW, *RETURN instructions terminate current SPB.
when (insn.opcode) {
Opcodes.GOTO,
Opcodes.ATHROW,
in Opcodes.IRETURN..Opcodes.RETURN ->
current = 0
}
}
}
fun getFrame(insn: AbstractInsnNode): Frame<V>? =
frames[insn.indexOf()]
private fun checkAssertions() {
if (insnsArray.any { it.opcode == Opcodes.JSR || it.opcode == Opcodes.RET })
throw AssertionError("Subroutines are deprecated since Java 6")
}
private fun visitOpInsn(current: Frame<V>, insn: Int) {
mergeControlFlowEdge(insn, insn + 1, current)
}
private fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = insnNode.dflt.indexOf()
mergeControlFlowEdge(insn, jump, current)
// In most cases order of visiting switch labels should not matter
// The only one is a tableswitch being added in the beginning of coroutine method, these switch' labels may lead
// in the middle of try/catch block, and FixStackAnalyzer is not ready for this (trying to restore stack before it was saved)
// So we just fix the order of labels being traversed: the first one should be one at the method beginning
// Using 'reversed' is because nodes are processed in LIFO order
for (label in insnNode.labels.reversed()) {
jump = label.indexOf()
mergeControlFlowEdge(insn, jump, current)
}
}
private fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = insnNode.dflt.indexOf()
mergeControlFlowEdge(insn, jump, current)
for (label in insnNode.labels) {
jump = label.indexOf()
mergeControlFlowEdge(insn, jump, current)
}
}
private fun visitJumpInsnNode(insnNode: JumpInsnNode, current: Frame<V>, insn: Int, insnOpcode: Int) {
if (insnOpcode != Opcodes.GOTO) {
mergeControlFlowEdge(insn, insn + 1, current)
}
val jump = insnNode.label.indexOf()
mergeControlFlowEdge(insn, jump, current)
}
private fun visitNopInsn(f: Frame<V>, insn: Int) {
mergeControlFlowEdge(insn, insn + 1, f)
}
private fun initControlFlowAnalysis(current: Frame<V>, m: MethodNode, owner: String) {
current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)))
val args = Type.getArgumentTypes(m.desc)
var local = 0
if ((m.access and Opcodes.ACC_STATIC) == 0) {
val ctype = Type.getObjectType(owner)
current.setLocal(local++, interpreter.newValue(ctype))
}
for (arg in args) {
current.setLocal(local++, interpreter.newValue(arg))
if (arg.size == 2) {
current.setLocal(local++, interpreter.newValue(null))
}
}
while (local < m.maxLocals) {
current.setLocal(local++, interpreter.newValue(null))
}
mergeControlFlowEdge(0, 0, current)
}
private fun computeExceptionHandlersForEachInsn(m: MethodNode) {
for (tcb in m.tryCatchBlocks) {
val begin = tcb.start.indexOf()
val end = tcb.end.indexOf()
for (j in begin until end) {
if (!insnsArray[j].isMeaningful) continue
var insnHandlers: MutableList<TryCatchBlockNode>? = handlers[j]
if (insnHandlers == null) {
insnHandlers = SmartList()
handlers[j] = insnHandlers
}
insnHandlers.add(tcb)
}
}
}
private fun mergeControlFlowEdge(src: Int, dest: Int, frame: Frame<V>) {
val oldFrame = frames[dest]
val changes = when {
oldFrame == null -> {
frames[dest] = newFrame(frame.locals, frame.maxStackSize).apply { init(frame) }
true
}
dest == src + 1 && singlePredBlock[src] == singlePredBlock[dest] -> {
// Forward jump within a single predecessor block, no need to merge.
oldFrame.init(frame)
true
}
else ->
oldFrame.merge(frame, interpreter)
}
if (changes && !queued[dest]) {
queued[dest] = true
queue[top++] = dest
}
}
@Suppress("unused")
private fun dumpBlocksInfo() {
fun LabelNode?.labelText() =
if (this != null) "L#${indexOf()}" else "L<null>"
println("===== ${method.name} ${method.signature} ======")
for ((i, insn) in insnsArray.withIndex()) {
val insnText = when (insn) {
is LabelNode ->
"L#$i"
is JumpInsnNode ->
"${insn.insnOpcodeText} ${insn.label.labelText()}"
is TableSwitchInsnNode ->
"${insn.insnOpcodeText} min=${insn.min} max=${insn.max} \n\t\t\t" +
"[${insn.labels.joinToString { it.labelText() }}] \n\t\t\t" +
"dflt:${insn.dflt.labelText()}"
is LookupSwitchInsnNode ->
"${insn.insnOpcodeText} \n\t\t\t" +
"[${insn.keys.zip(insn.labels).joinToString { (key, label) -> "$key: ${label.labelText()}"}}] \n\t\t\t" +
"dflt:${insn.dflt.labelText()}"
else ->
insn.insnText
}
println("$i\t${singlePredBlock[i]}\t$insnText")
}
for (tcb in method.tryCatchBlocks) {
println("\tTCB start:${tcb.start.labelText()} end:${tcb.end.labelText()} handler:${tcb.handler.labelText()}")
}
println()
}
}

View File

@@ -1,6 +1,35 @@
/*
* 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.
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jetbrains.kotlin.codegen.optimization.common
@@ -95,7 +124,7 @@ class InstructionLivenessAnalyzer(val method: MethodNode) {
var jump = insnNode.dflt.indexOf
visitControlFlowEdge(jump)
for (label in insnNode.labels) {
jump = instructions.indexOf(label)
jump = label.indexOf
visitControlFlowEdge(jump)
}
}
@@ -126,9 +155,10 @@ class InstructionLivenessAnalyzer(val method: MethodNode) {
val begin = tcb.start.indexOf
val end = tcb.end.indexOf
for (j in begin until end) {
if (!instructions[j].isMeaningful) continue
var insnHandlers = handlers[j]
if (insnHandlers == null) {
insnHandlers = ArrayList<TryCatchBlockNode>()
insnHandlers = ArrayList()
handlers[j] = insnHandlers
}
insnHandlers.add(tcb)

View File

@@ -1,263 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.kotlin.codegen.inline.insnText
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
import java.util.*
/**
* This class is a modified version of `org.objectweb.asm.tree.analysis.Analyzer`
* @author Eric Bruneton
* @author Dmitry Petrov
*/
open class MethodAnalyzer<V : Value>(
private val owner: String,
val method: MethodNode,
protected val interpreter: Interpreter<V>
) {
val instructions: InsnList = method.instructions
private val nInsns: Int = instructions.size()
val frames: Array<Frame<V>?> = arrayOfNulls(nInsns)
private val handlers: Array<MutableList<TryCatchBlockNode>?> = arrayOfNulls(nInsns)
private val queued: BooleanArray = BooleanArray(nInsns)
private val queue: IntArray = IntArray(nInsns)
private var top: Int = 0
protected open fun init(owner: String, m: MethodNode) {}
protected open fun newFrame(nLocals: Int, nStack: Int): Frame<V> = Frame(nLocals, nStack)
protected open fun newFrame(src: Frame<out V>): Frame<V> {
val frame = newFrame(src.locals, src.maxStackSize)
frame.init(src)
return frame
}
protected open fun visitControlFlowEdge(insn: Int, successor: Int): Boolean = true
protected open fun visitControlFlowExceptionEdge(insn: Int, successor: Int): Boolean = true
protected open fun visitControlFlowExceptionEdge(insn: Int, tcb: TryCatchBlockNode): Boolean =
visitControlFlowExceptionEdge(insn, instructions.indexOf(tcb.handler))
fun analyze(): Array<Frame<V>?> {
if (nInsns == 0) return frames
checkAssertions()
computeExceptionHandlersForEachInsn(method)
val current = newFrame(method.maxLocals, method.maxStack)
val handler = newFrame(method.maxLocals, method.maxStack)
initControlFlowAnalysis(current, method, owner)
while (top > 0) {
val insn = queue[--top]
val f = frames[insn]!!
queued[insn] = false
val insnNode = method.instructions[insn]
try {
val insnOpcode = insnNode.opcode
val insnType = insnNode.type
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
visitNopInsn(f, insn)
} else {
current.init(f).execute(insnNode, interpreter)
when {
insnNode is JumpInsnNode ->
visitJumpInsnNode(insnNode, current, insn, insnOpcode)
insnNode is LookupSwitchInsnNode ->
visitLookupSwitchInsnNode(insnNode, current, insn)
insnNode is TableSwitchInsnNode ->
visitTableSwitchInsnNode(insnNode, current, insn)
insnOpcode != Opcodes.ATHROW && (insnOpcode < Opcodes.IRETURN || insnOpcode > Opcodes.RETURN) ->
visitOpInsn(current, insn)
else -> {
}
}
}
handlers[insn]?.forEach { tcb ->
val exnType = Type.getObjectType(tcb.type ?: "java/lang/Throwable")
val jump = instructions.indexOf(tcb.handler)
if (visitControlFlowExceptionEdge(insn, tcb)) {
handler.init(f)
handler.clearStack()
handler.push(interpreter.newValue(exnType))
mergeControlFlowEdge(jump, handler)
}
}
} catch (e: AnalyzerException) {
throw AnalyzerException(e.node, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
} catch (e: Exception) {
throw AnalyzerException(insnNode, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
}
}
return frames
}
fun getFrame(insn: AbstractInsnNode): Frame<V>? =
frames[instructions.indexOf(insn)]
private fun checkAssertions() {
if (instructions.toArray().any { it.opcode == Opcodes.JSR || it.opcode == Opcodes.RET })
throw AssertionError("Subroutines are deprecated since Java 6")
}
private fun visitOpInsn(current: Frame<V>, insn: Int) {
processControlFlowEdge(current, insn, insn + 1)
}
private fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = instructions.indexOf(insnNode.dflt)
processControlFlowEdge(current, insn, jump)
// In most cases order of visiting switch labels should not matter
// The only one is a tableswitch being added in the beginning of coroutine method, these switch' labels may lead
// in the middle of try/catch block, and FixStackAnalyzer is not ready for this (trying to restore stack before it was saved)
// So we just fix the order of labels being traversed: the first one should be one at the method beginning
// Using 'reversed' is because nodes are processed in LIFO order
for (label in insnNode.labels.reversed()) {
jump = instructions.indexOf(label)
processControlFlowEdge(current, insn, jump)
}
}
private fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = instructions.indexOf(insnNode.dflt)
processControlFlowEdge(current, insn, jump)
for (label in insnNode.labels) {
jump = instructions.indexOf(label)
processControlFlowEdge(current, insn, jump)
}
}
private fun visitJumpInsnNode(insnNode: JumpInsnNode, current: Frame<V>, insn: Int, insnOpcode: Int) {
if (insnOpcode != Opcodes.GOTO && insnOpcode != Opcodes.JSR) {
processControlFlowEdge(current, insn, insn + 1)
}
val jump = instructions.indexOf(insnNode.label)
processControlFlowEdge(current, insn, jump)
}
private fun visitNopInsn(f: Frame<V>, insn: Int) {
processControlFlowEdge(f, insn, insn + 1)
}
private fun processControlFlowEdge(current: Frame<V>, insn: Int, jump: Int) {
if (visitControlFlowEdge(insn, jump)) {
mergeControlFlowEdge(jump, current)
}
}
private fun initControlFlowAnalysis(current: Frame<V>, m: MethodNode, owner: String) {
current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)))
val args = Type.getArgumentTypes(m.desc)
var local = 0
if ((m.access and Opcodes.ACC_STATIC) == 0) {
val ctype = Type.getObjectType(owner)
current.setLocal(local++, interpreter.newValue(ctype))
}
for (arg in args) {
current.setLocal(local++, interpreter.newValue(arg))
if (arg.size == 2) {
current.setLocal(local++, interpreter.newValue(null))
}
}
while (local < m.maxLocals) {
current.setLocal(local++, interpreter.newValue(null))
}
mergeControlFlowEdge(0, current)
init(owner, m)
}
private fun computeExceptionHandlersForEachInsn(m: MethodNode) {
for (tcb in m.tryCatchBlocks) {
val begin = instructions.indexOf(tcb.start)
val end = instructions.indexOf(tcb.end)
for (j in begin until end) {
var insnHandlers: MutableList<TryCatchBlockNode>? = handlers[j]
if (insnHandlers == null) {
insnHandlers = ArrayList<TryCatchBlockNode>()
handlers[j] = insnHandlers
}
insnHandlers.add(tcb)
}
}
}
private fun mergeControlFlowEdge(insn: Int, frame: Frame<V>) {
val oldFrame = frames[insn]
val changes =
if (oldFrame != null)
oldFrame.merge(frame, interpreter)
else {
frames[insn] = newFrame(frame)
true
}
if (changes && !queued[insn]) {
queued[insn] = true
queue[top++] = insn
}
}
}

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