Compare commits

..

1 Commits

Author SHA1 Message Date
Ilmir Usmanov
f6bd1328fb 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 16:32:14 +02:00
51174 changed files with 1171803 additions and 38105 deletions

View File

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

20
.idea/runConfigurations/IDEA.xml generated Normal file
View File

@@ -0,0 +1,20 @@
<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

@@ -0,0 +1,20 @@
<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

@@ -0,0 +1,20 @@
<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

@@ -0,0 +1,20 @@
<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

@@ -0,0 +1,19 @@
<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

@@ -1,23 +0,0 @@
<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>

View File

@@ -1,307 +1,5 @@
# CHANGELOG
## 1.5.21
### Compiler
- [`KT-47320`](https://youtrack.jetbrains.com/issue/KT-47320) "StringConcatException: Mismatched number of concat arguments" String concatenation fails when template contains special character
- [`KT-47445`](https://youtrack.jetbrains.com/issue/KT-47445) "definitely not null type parameters is only available since language version 1.6" error in cast expression
- [`KT-47446`](https://youtrack.jetbrains.com/issue/KT-47446) Improve warning message INTEGER_OPERATOR_RESOLVE_WILL_CHANGE
- [`KT-47447`](https://youtrack.jetbrains.com/issue/KT-47447) False positive INTEGER_OPERATOR_RESOLVE_WILL_CHANGE warning: "expression will be resolved to Int in future releases"
- [`KT-47449`](https://youtrack.jetbrains.com/issue/KT-47449) JVM / IR: ClassCastException IrStarProjectionImpl cannot be cast to IrTypeProjection
- [`KT-47459`](https://youtrack.jetbrains.com/issue/KT-47459) "IndexOutOfBoundsException: Index 0 out of bounds for length 0" caused by MarkertManager dependency
- [`KT-47480`](https://youtrack.jetbrains.com/issue/KT-47480) StackOverflowError: Recursion on erasion of raw type with interdependent type parameters
### Tools. Compiler Plugins
- [`KT-47161`](https://youtrack.jetbrains.com/issue/KT-47161) Serializable class can't be inherited from serializable class in other module with: e: org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Couldn't transform method node: write$Self
- [`KT-47455`](https://youtrack.jetbrains.com/issue/KT-47455) Kotlin lombok plugin NullPointerException
- [`KT-47513`](https://youtrack.jetbrains.com/issue/KT-47513) Lombok compiler plugin failed with 'Recursion detected in a lazy value under LockBasedStorageManager@1c21db60 (TopDownAnalyzer for JVM)'
### Tools. Gradle
- [`KT-47444`](https://youtrack.jetbrains.com/issue/KT-47444) Gradle Plugin: Publishing project with "maven-publish" fails when dependency versions are omitted (NPE in MppDependencyRewritingUtilsKt.associateDependenciesWithActualModuleDependencies)
### Tools. kapt
- [`KT-47416`](https://youtrack.jetbrains.com/issue/KT-47416) Kapt Gradle DSL ignores javaCompilerOptions in 1.5.20
## 1.5.20
### Compiler
#### New Features
- [`KT-43262`](https://youtrack.jetbrains.com/issue/KT-43262) No error for Java generic class @NotNull type parameter used in Kotlin with nullable type argument
- [`KT-44373`](https://youtrack.jetbrains.com/issue/KT-44373) FIR: support error / warning suppression
- [`KT-45189`](https://youtrack.jetbrains.com/issue/KT-45189) Support nullability annotations at module level
- [`KT-45284`](https://youtrack.jetbrains.com/issue/KT-45284) Emit warnings based on jspecify annotations
- [`KT-45525`](https://youtrack.jetbrains.com/issue/KT-45525) Allow to omit JvmInline annotation for expect value classes
- [`KT-46545`](https://youtrack.jetbrains.com/issue/KT-46545) Emit annotations on function type parameters into bytecode for -jvm-target 1.8 and above
#### Performance Improvements
- [`KT-36646`](https://youtrack.jetbrains.com/issue/KT-36646) Don't box primitive values in equality comparison with objects in JVM_IR
#### Fixes
- [`KT-8325`](https://youtrack.jetbrains.com/issue/KT-8325) Unresolved annotation should be an error
- [`KT-19455`](https://youtrack.jetbrains.com/issue/KT-19455) Type annotation unresolved on a type parameter of a supertype in anonymous object expression
- [`KT-24643`](https://youtrack.jetbrains.com/issue/KT-24643) Prohibit using a type parameter declared for an extension property inside delegate
- [`KT-25876`](https://youtrack.jetbrains.com/issue/KT-25876) Annotations on return types and supertypes are not analyzed
- [`KT-28449`](https://youtrack.jetbrains.com/issue/KT-28449) Annotation target is not analyzed in several cases for type annotations
- [`KT-36770`](https://youtrack.jetbrains.com/issue/KT-36770) Prohibit unsafe calls with expected @NotNull T and given Kotlin generic parameter with nullable bound
- [`KT-36880`](https://youtrack.jetbrains.com/issue/KT-36880) K/N IR: Reference to expect property in actual declaration is not remapped
- [`KT-38325`](https://youtrack.jetbrains.com/issue/KT-38325) IllegalStateException: No parameter with index 0-0 when iterating Scala 2.12.11 List
- [`KT-38342`](https://youtrack.jetbrains.com/issue/KT-38342) FIR: Consider renaming diagnostic from AMBIGUITY to OVERLOAD_RESOLUTION_AMBIGUITY
- [`KT-38476`](https://youtrack.jetbrains.com/issue/KT-38476) [FIR] Forgotten type approximation
- [`KT-38540`](https://youtrack.jetbrains.com/issue/KT-38540) Kotlin/Native Set<T>.contains fails with specific enum setup
- [`KT-40425`](https://youtrack.jetbrains.com/issue/KT-40425) IrGenerationExtension. Support simple reporting to compiler output (for development/debug)
- [`KT-41620`](https://youtrack.jetbrains.com/issue/KT-41620) ClassCastException: Class cannot be cast to java.lang.Void
- [`KT-41679`](https://youtrack.jetbrains.com/issue/KT-41679) NI: TYPE_MISMATCH wrong type inference of collection with type Any and integer literal
- [`KT-41818`](https://youtrack.jetbrains.com/issue/KT-41818) NI: False positive IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION leads to NothingValueException on delegated properties
- [`KT-42239`](https://youtrack.jetbrains.com/issue/KT-42239) IR: Report compilation error instead of throwing an exception (effectively crash compiler) when some declaration wasn't found while deserialization
- [`KT-42631`](https://youtrack.jetbrains.com/issue/KT-42631) ArrayIndexOutOfBoundsException was thrown during IR lowering
- [`KT-43258`](https://youtrack.jetbrains.com/issue/KT-43258) NI: False positive "Suspend function 'invoke' should be called only from a coroutine or another suspend function" when calling suspend operator fun on object property from last expression of a crossinlined suspend lambda
- [`KT-44036`](https://youtrack.jetbrains.com/issue/KT-44036) Enum initialization order
- [`KT-44511`](https://youtrack.jetbrains.com/issue/KT-44511) FIR DFA: smartcast after `if (nullable ?: boolean)`
- [`KT-44554`](https://youtrack.jetbrains.com/issue/KT-44554) RAW FIR: NPE in RawFirBuilder
- [`KT-44682`](https://youtrack.jetbrains.com/issue/KT-44682) raw FIR: incorrect source for qualified access
- [`KT-44695`](https://youtrack.jetbrains.com/issue/KT-44695) *_TYPE_MISMATCH_ON_OVERRIDE checkers do not work for anonymous objects
- [`KT-44699`](https://youtrack.jetbrains.com/issue/KT-44699) FIR: incorrect lambda return type (led to a false alarm: PROPERTY_TYPE_MISMATCH_ON_OVERRIDE)
- [`KT-44802`](https://youtrack.jetbrains.com/issue/KT-44802) FIR bootstrap: trying to access package private class
- [`KT-44813`](https://youtrack.jetbrains.com/issue/KT-44813) FIR bootstrap: various errors in collection-like classes
- [`KT-44814`](https://youtrack.jetbrains.com/issue/KT-44814) FIR bootstrap: incorrect cast in when branch
- [`KT-44942`](https://youtrack.jetbrains.com/issue/KT-44942) [FIR] ClassCastException in boostrap tests
- [`KT-44995`](https://youtrack.jetbrains.com/issue/KT-44995) FIR: false positive for ANNOTATION_ARGUMENT_MUST_BE_CONST
- [`KT-45010`](https://youtrack.jetbrains.com/issue/KT-45010) FIR: lambda arguments of inapplicable call is not resolved
- [`KT-45048`](https://youtrack.jetbrains.com/issue/KT-45048) FIR bootstrap: VerifyError on KtUltraLightClass
- [`KT-45052`](https://youtrack.jetbrains.com/issue/KT-45052) FIR bootstrap: inapplicable candidate in GenerateSpecTests.kt
- [`KT-45121`](https://youtrack.jetbrains.com/issue/KT-45121) FIR IDE: redundant vararg parameter type transformation
- [`KT-45136`](https://youtrack.jetbrains.com/issue/KT-45136) Native: dividing Int.MIN_VALUE by -1 crashes or hangs
- [`KT-45236`](https://youtrack.jetbrains.com/issue/KT-45236) JVM / IR: "IllegalStateException: Symbol with IrTypeParameterSymbolImpl is unbound" caused by contracts and sealed class
- [`KT-45308`](https://youtrack.jetbrains.com/issue/KT-45308) Psi2ir: "AssertionError: TypeAliasDescriptor expected" caused by using typealias from one module as a type in another module without a transitive dependency
- [`KT-45316`](https://youtrack.jetbrains.com/issue/KT-45316) [FIR] Ambiguity between two implicit invokes with receiver
- [`KT-45344`](https://youtrack.jetbrains.com/issue/KT-45344) FIR: Wrong inferred type for nullable type parameter
- [`KT-45385`](https://youtrack.jetbrains.com/issue/KT-45385) FIR: false positive MUST_BE_INITIALIZED_OR_BE_ABSTRACT after rethrow
- [`KT-45475`](https://youtrack.jetbrains.com/issue/KT-45475) [FIR] No smartcast after throw in if inside try block
- [`KT-45508`](https://youtrack.jetbrains.com/issue/KT-45508) False negative ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED on a fake override with an abstract super class member
- [`KT-45578`](https://youtrack.jetbrains.com/issue/KT-45578) REPL: Unresolved imports are cached for the subsequent compilations
- [`KT-45685`](https://youtrack.jetbrains.com/issue/KT-45685) JVM IR: capturing a variable into crossinline suspend lambda makes the function inside inline function no longer unbox Result
- [`KT-45584`](https://youtrack.jetbrains.com/issue/KT-45584) [FIR] Fix overriding property and java function in java class
- [`KT-45697`](https://youtrack.jetbrains.com/issue/KT-45697) JVM IR: ISE "Function has no body" on getter of private field in a class present both in sources and dependencies
- [`KT-45842`](https://youtrack.jetbrains.com/issue/KT-45842) Compiler doesn't allow a shared class to inherit a platform-specific sealed class
- [`KT-45848`](https://youtrack.jetbrains.com/issue/KT-45848) False negative [SEALED_INHERITOR_IN_DIFFERENT_MODULE] error in compiler for a platform-specific inheritor of a shared sealed class
- [`KT-45931`](https://youtrack.jetbrains.com/issue/KT-45931) There is no warning based on nullability java annotation
- [`KT-45998`](https://youtrack.jetbrains.com/issue/KT-45998) JVM IR: AE when an accessor to a protected companion object member is being generated in child class
- [`KT-46048`](https://youtrack.jetbrains.com/issue/KT-46048) Enum entries init order in companion object
- [`KT-46074`](https://youtrack.jetbrains.com/issue/KT-46074) FIR: private-in-file fun interface is considered invisible in this file
- [`KT-46173`](https://youtrack.jetbrains.com/issue/KT-46173) No error reporting on annotations on target type of `as` expression in return
- [`KT-46235`](https://youtrack.jetbrains.com/issue/KT-46235) JVM IR: Stack overflow error on large expressions
- [`KT-46270`](https://youtrack.jetbrains.com/issue/KT-46270) [FIR] Support `@PublishedAPI` in inline checker
- [`KT-46539`](https://youtrack.jetbrains.com/issue/KT-46539) Generate annotations on type parameters bounds in bytecode
- [`KT-46578`](https://youtrack.jetbrains.com/issue/KT-46578) JVM IR: IllegalAccessError accessing property delegated to java super class protected field reference
- [`KT-46597`](https://youtrack.jetbrains.com/issue/KT-46597) JVM IR: AssertionError: SyntheticAccessorLowering should not attempt to modify other files - crossinline accessor
- [`KT-46601`](https://youtrack.jetbrains.com/issue/KT-46601) JVM / IR: IllegalStateException: "Can't find method 'invokeinvoke`" when default lambda takes inline class parameters
- [`KT-46670`](https://youtrack.jetbrains.com/issue/KT-46670) StackOverflowError on inheritance from raw type where class has protobuf-like recursive generics
- [`KT-46715`](https://youtrack.jetbrains.com/issue/KT-46715) JVM / IR: "AssertionError: Unbound symbols not allowed IrConstructorSymbolImpl" with enum classes with the same name in test and src folders
- [`KT-46759`](https://youtrack.jetbrains.com/issue/KT-46759) JVM IR: CCE in LateinitUsageLowering on @JvmStatic lateinit property in object
- [`KT-46777`](https://youtrack.jetbrains.com/issue/KT-46777) [Native] [IR] Support suspend function as super type
- [`KT-46802`](https://youtrack.jetbrains.com/issue/KT-46802) JVM / IR: "UnsupportedOperationException: Unknown structure of ADAPTER_FOR_CALLABLE_REFERENCE" caused by function reference on @JvmStatic function with unused default parameters
- [`KT-46813`](https://youtrack.jetbrains.com/issue/KT-46813) JVM / IR: "ClassCastException: Integer cannot be cast to class Result" with Flow and `fold` method
- [`KT-46822`](https://youtrack.jetbrains.com/issue/KT-46822) JVM IR: StackOverflowError on compiling a large data class
- [`KT-46837`](https://youtrack.jetbrains.com/issue/KT-46837) Backend Internal error: Exception during IR lowering: assert at IrOverridingUtilKt.buildFakeOverrideMember
- [`KT-46921`](https://youtrack.jetbrains.com/issue/KT-46921) JVM / IR: "IndexOutOfBoundsException: Cannot pop operand off an empty stack" caused by crossinline parameter and label return
- [`KT-46984`](https://youtrack.jetbrains.com/issue/KT-46984) Type parameter bounds aren't used to report corresponding mismatch warnings
- [`KT-46985`](https://youtrack.jetbrains.com/issue/KT-46985) There aren't warnings by java nullability annotations
- [`KT-46986`](https://youtrack.jetbrains.com/issue/KT-46986) There aren't warnings by java nullability annotations
- [`KT-46989`](https://youtrack.jetbrains.com/issue/KT-46989) There aren't warnings by java nullability annotations
- [`KT-46990`](https://youtrack.jetbrains.com/issue/KT-46990) There aren't warnings by java nullability annotations on method's violated type arguments
- [`KT-47019`](https://youtrack.jetbrains.com/issue/KT-47019) K/N: IrProperty.overriddenSymbols can't be used in common IR backend modules yet because it doesn't fully work in Native
### Docs & Examples
- [`KT-33783`](https://youtrack.jetbrains.com/issue/KT-33783) Document when a range created with rangeTo is empty
### IDE
- [`KT-44638`](https://youtrack.jetbrains.com/issue/KT-44638) `clone()` call is unresolved in JVM module of a multiplatform project
- [`KT-45629`](https://youtrack.jetbrains.com/issue/KT-45629) [ULC] KtUltraLightFieldForSourceDeclaration.nameIdentifier returns null
- [`KT-44825`](https://youtrack.jetbrains.com/issue/KT-44825) Can't open Kotlin compiler settings in newly created project
- [`KT-45908`](https://youtrack.jetbrains.com/issue/KT-45908) Reproduciable 'org.jetbrains.kotlin.idea.caches.resolve.KotlinIdeaResolutionException: Kotlin resolution encountered a problem while analyzing KtNameReferenceExpression'
### IDE. FIR
- [`KT-45175`](https://youtrack.jetbrains.com/issue/KT-45175) FIR IDE: Exception with local property in `init` block
- [`KT-45199`](https://youtrack.jetbrains.com/issue/KT-45199) FIR IDE: Error while collecting diagnostic on stale element after replacing element in quickfix
- [`KT-45312`](https://youtrack.jetbrains.com/issue/KT-45312) FIR IDE: FIR plugin throws exception on synthetic function
### IDE. Gradle Integration
- [`KT-34401`](https://youtrack.jetbrains.com/issue/KT-34401) KotlinGradleModelBuilder builds models for non-kotlin modules and always trigger full task configuration.
- [`KT-45277`](https://youtrack.jetbrains.com/issue/KT-45277) Wrong jvm target in gradle module in IDEA
- [`KT-46488`](https://youtrack.jetbrains.com/issue/KT-46488) Import of a multiplatform project with MPP module depending on Kotlin/JVM one fails
### IDE. Inspections and Intentions
- [`KT-45075`](https://youtrack.jetbrains.com/issue/KT-45075) Inspection: Redundant creation of Json format
- [`KT-45347`](https://youtrack.jetbrains.com/issue/KT-45347) Sealed interfaces: quickfix to move to package/module of sealed class/interface should not be shown in case of read-only declaration
- [`KT-45348`](https://youtrack.jetbrains.com/issue/KT-45348) Sealed interfaces: show error for usage of sealed class/interface from a library in Java source code
- [`KT-46063`](https://youtrack.jetbrains.com/issue/KT-46063) In multiplatform code, suggest to generate remaining `when` branches at least for shared sealed classes
### IDE. Refactorings
- [`KT-44431`](https://youtrack.jetbrains.com/issue/KT-44431) Quickfix to move class/interface to proper location: it is allowed to choose test source in JPS project while compiler does not allow it
### IDE. Native
- [`KT-39320`](https://youtrack.jetbrains.com/issue/KT-39320) [Commonizer] Reduce memory consumption
### JavaScript
- [`KT-40235`](https://youtrack.jetbrains.com/issue/KT-40235) KJS: IR. Broken support for external interface companion
- [`KT-40689`](https://youtrack.jetbrains.com/issue/KT-40689) KJS / IR: strange and slow code for kotlin.math.max and kotlin.math.min for Double
- [`KT-44138`](https://youtrack.jetbrains.com/issue/KT-44138) KJS / IR: Constant folding works incorrectly with unsigned arithmetic
- [`KT-44394`](https://youtrack.jetbrains.com/issue/KT-44394) KJS / IR: `null` companion object for existed stdlib interfaces `NodeFilter` and `SVGUnitTypes`
- [`KT-44950`](https://youtrack.jetbrains.com/issue/KT-44950) KJS / IR: "IllegalStateException: Can't find name for declaration" in case of extending export declared class without @JsExport annotation
- [`KT-45057`](https://youtrack.jetbrains.com/issue/KT-45057) KJS / IR: "ClassCastException" when using `js` function in init block
- [`KT-45361`](https://youtrack.jetbrains.com/issue/KT-45361) KJS / IR: `IrConstructorCall` representing annotation always returns `Unit`
- [`KT-46608`](https://youtrack.jetbrains.com/issue/KT-46608) KJS: "Could not load content..." for source maps
- [`KT-45655`](https://youtrack.jetbrains.com/issue/KT-45655) KJS: "REINTERPRET_CAST" is not copyable
- [`KT-45866`](https://youtrack.jetbrains.com/issue/KT-45866) Default parameter with generic in expect-actual declarations
- [`KT-46859`](https://youtrack.jetbrains.com/issue/KT-46859) Exception during IR lowering: NullPointerException was thrown at: optimizations.FoldConstantLowering.tryFoldingUnaryOps
### KMM Plugin
- [`KT-43899`](https://youtrack.jetbrains.com/issue/KT-43899) KMM: Fix "stale framework" usage by XCode & AppCode in default build script
### Libraries
- [`KT-43701`](https://youtrack.jetbrains.com/issue/KT-43701) Stdlib: Expand KDoc of inc() and dec() for operators
- [`KT-46002`](https://youtrack.jetbrains.com/issue/KT-46002) Support all Unicode digit chars in digitToInt (JS and Native)
- [`KT-46183`](https://youtrack.jetbrains.com/issue/KT-46183) Add default value for ignoreCase in K/N String.replace/replaceFirst
- [`KT-46184`](https://youtrack.jetbrains.com/issue/KT-46184) Equivalize isLowerCase and isUpperCase behavior in all platforms
### Native
- [`KT-33175`](https://youtrack.jetbrains.com/issue/KT-33175) IR: String constants with incorrect surrogate pairs aren't preserved during serialization/deserialization
- [`KT-44799`](https://youtrack.jetbrains.com/issue/KT-44799) Different behavior with functional interfaces in Kotlin/Native on iOS
### Native. C Export
- [`KT-42796`](https://youtrack.jetbrains.com/issue/KT-42796) [Reverse C Interop] Package with no public methods generate empty struct in the header, leading to an error
### Native. ObjC Export
- [`KT-38600`](https://youtrack.jetbrains.com/issue/KT-38600) Kotlin MP iOS Target doesn't contain kdoc comments
- [`KT-45127`](https://youtrack.jetbrains.com/issue/KT-45127) KMM: hard to pass an error to Kotlin code from implementation of Kotlin method in Swift code
### Native. Runtime. Memory
- [`KT-45063`](https://youtrack.jetbrains.com/issue/KT-45063) Profiling indicates that a lot of time is spent on updateHeapRef on Apple platforms when running KMP code
### Reflection
- [`KT-10838`](https://youtrack.jetbrains.com/issue/KT-10838) Provide sensible toString() for property accessors in reflection
- [`KT-13490`](https://youtrack.jetbrains.com/issue/KT-13490) Equality doesn't work for KProperty.Accessor implementations
### Tools. CLI
- [`KT-14772`](https://youtrack.jetbrains.com/issue/KT-14772) ISE (FNFE "Not a directory") on compilation with destination argument clashing with an existing file which is not a directory
- [`KT-18184`](https://youtrack.jetbrains.com/issue/KT-18184) CompileEnvironmentException: Invalid jar path on "-d" with .jar in non-existing directory
- [`KT-40977`](https://youtrack.jetbrains.com/issue/KT-40977) Report a readable diagnostic on empty -J argument in CLI
### Tools. Commonizer
- [`KT-45497`](https://youtrack.jetbrains.com/issue/KT-45497) [Commonizer] c-interop commonization: Dependency commonization
- [`KT-46077`](https://youtrack.jetbrains.com/issue/KT-46077) [Commonizer] Add `commonizer_target` to commonized klib's manifest
- [`KT-46107`](https://youtrack.jetbrains.com/issue/KT-46107) [Commonizer] CInteropCommonizerTask receives faulty dependencies in multi module projects containing multiple c-interops
- [`KT-46248`](https://youtrack.jetbrains.com/issue/KT-46248) MPP: Compile KotlinMetadata fails with Unresolved reference if only one native platform from shared source set is available
- [`KT-46856`](https://youtrack.jetbrains.com/issue/KT-46856) [Commonizer] Many targets can fail with 'filename too long'
### Tools. Compiler Plugins
- [`KT-7112`](https://youtrack.jetbrains.com/issue/KT-7112) Support calling Lombok-generated methods within same module
- [`KT-45538`](https://youtrack.jetbrains.com/issue/KT-45538) Serialization, JVM IR: "AssertionError: No such type argument slot in IrConstructorCallImpl" with inner classes
- [`KT-45541`](https://youtrack.jetbrains.com/issue/KT-45541) JVM / IR / Serialization: NullPointerException caused by "Serializable" annotation and local data class
- [`KT-46469`](https://youtrack.jetbrains.com/issue/KT-46469) Kotlin Lombok: accessors with `AccessLevel.MODULE` fail to resolve
- [`KT-46529`](https://youtrack.jetbrains.com/issue/KT-46529) Kotlin Lombok: with `@Accessors` without explicit `prefix` the prefix from lombok.config is not taken into account
- [`KT-46531`](https://youtrack.jetbrains.com/issue/KT-46531) Kotlin Lombok: `lombok.getter.noIsPrefix` is processed depending on character case
- [`KT-46920`](https://youtrack.jetbrains.com/issue/KT-46920) NullPointerException in CodeGeneratorVisitor when packing for xcode
### Tools. Gradle
- [`KT-24533`](https://youtrack.jetbrains.com/issue/KT-24533) Kapt should not run when annotation processors are not configured
- [`KT-43988`](https://youtrack.jetbrains.com/issue/KT-43988) Enable plugin validation during build
- [`KT-45301`](https://youtrack.jetbrains.com/issue/KT-45301) Gradle: Empty `build/kotlin` dir with custom build directory
- [`KT-45519`](https://youtrack.jetbrains.com/issue/KT-45519) loadAndroidPluginVersion() impacts performance negatively and noticeably in multimodule Android build
- [`KT-45744`](https://youtrack.jetbrains.com/issue/KT-45744) Create Kotlin Gradle Plugin JUnit5 basic test setup
- [`KT-45834`](https://youtrack.jetbrains.com/issue/KT-45834) Gradle Plugin read system property related to kotlinCompilerClasspath breaks use of configuration cache
- [`KT-46401`](https://youtrack.jetbrains.com/issue/KT-46401) Deprecate 'kotlin.parallel.tasks.in.project' build property
- [`KT-46820`](https://youtrack.jetbrains.com/issue/KT-46820) Gradle: kotlinc (1.5.0) race condition causes a NullPointerException
- [`KT-47317`](https://youtrack.jetbrains.com/issue/KT-47317) Restore 'kotlinPluginVersion' property in 'KotlinBasePluginWrapper'
### Tools. Gradle. JS
- [`KT-42911`](https://youtrack.jetbrains.com/issue/KT-42911) Support Gradle configuration cache for K/JS tasks
- [`KT-45294`](https://youtrack.jetbrains.com/issue/KT-45294) KJS / Gradle: Number of modules in project affects JS tasks configuration cache state size
- [`KT-45754`](https://youtrack.jetbrains.com/issue/KT-45754) KJS / IR: Remove adding option of source maps in Gradle plugin
- [`KT-46178`](https://youtrack.jetbrains.com/issue/KT-46178) KJS / Dukat: Added as a dependency always without condition
- [`KT-46976`](https://youtrack.jetbrains.com/issue/KT-46976) KJS: Broken support for dynamically created `webpack.config.d`
- [`KT-47045`](https://youtrack.jetbrains.com/issue/KT-47045) [Gradle, JS] Task requirements are added to all compilations with same name
### Tools. Gradle. Multiplatform
- [`KT-36679`](https://youtrack.jetbrains.com/issue/KT-36679) MPP Gradle plugin: Improve messaging for the commonizer
- [`KT-45832`](https://youtrack.jetbrains.com/issue/KT-45832) CInteropCommonization: Filter out illegal dependencies
- [`KT-46394`](https://youtrack.jetbrains.com/issue/KT-46394) Multiplatform: Gradle 7 support
- [`KT-46517`](https://youtrack.jetbrains.com/issue/KT-46517) Add kotlin-project-model as api dependency to kotlin-gradle-plugin-api
### Tools. Gradle. Native
- [`KT-27240`](https://youtrack.jetbrains.com/issue/KT-27240) MPP Gradle plugin: Provide a framework packing task for Kotlin/Native
- [`KT-39016`](https://youtrack.jetbrains.com/issue/KT-39016) Missing stdlib when the downloading process was aborted
- [`KT-40907`](https://youtrack.jetbrains.com/issue/KT-40907) Xcode error after switching between device and simulator: Building for iOS, but the linked and embedded framework was built for iOS Simulator.
- [`KT-44059`](https://youtrack.jetbrains.com/issue/KT-44059) iosSimTest tasks are never up-to-date
- [`KT-45801`](https://youtrack.jetbrains.com/issue/KT-45801) compileIosMainKotlinMetadata compilation property of gradle task is not initialized and fails with `Execution failed for task ':shared:generateProjectStructureMetadata'`
- [`KT-46680`](https://youtrack.jetbrains.com/issue/KT-46680) Register concrete "embedAndSign" tasks instead umbrella
- [`KT-46892`](https://youtrack.jetbrains.com/issue/KT-46892) Kotlin Multiplatform Gradle Plugin: EmbedAndSign task always contains a default framework name
### Tools. Incremental Compile
- [`KT-44741`](https://youtrack.jetbrains.com/issue/KT-44741) Incremental compilation: inspectClassesForKotlinIC doesn't determine changes with imported constant
### Tools. JPS
- [`KT-34351`](https://youtrack.jetbrains.com/issue/KT-34351) KotlinTargetsIndex creation takes too long even if project doesn't have any kotlin
- [`KT-45191`](https://youtrack.jetbrains.com/issue/KT-45191) [JPS] Marking method as "default" in Java SAM interface doesn't affect dependencies
- [`KT-46242`](https://youtrack.jetbrains.com/issue/KT-46242) Support Lombok kotlin plugin in JPS and maven
### Tools. kapt
#### Performance Improvements
- [`KT-28901`](https://youtrack.jetbrains.com/issue/KT-28901) Consider caching annotation processors classloaders
#### Fixes
- [`KT-27123`](https://youtrack.jetbrains.com/issue/KT-27123) kapt: missing space in error log makes location non-clickable
- [`KT-29929`](https://youtrack.jetbrains.com/issue/KT-29929) [Kapt] Stub generator uses constant value in method annotation instead of constant name 2.
- [`KT-31146`](https://youtrack.jetbrains.com/issue/KT-31146) kapt: executableElement.getAnnotation(JvmOverloads::class.java) returns null
- [`KT-32202`](https://youtrack.jetbrains.com/issue/KT-32202) Gradle task kaptKotlin fails: "module not found" in Java 11 modular application
- [`KT-34838`](https://youtrack.jetbrains.com/issue/KT-34838) Kapt: 'cannot find symbol' for a top-level property with anonymous delegate
- [`KT-35104`](https://youtrack.jetbrains.com/issue/KT-35104) Support @JvmStatic in KAPT stubs
- [`KT-35167`](https://youtrack.jetbrains.com/issue/KT-35167) Kapt Gradle plugin doesn't handle --module-path javac argument
- [`KT-37586`](https://youtrack.jetbrains.com/issue/KT-37586) KAPT: When delegated property use an unknown type (to-be-generated class), `correctTypeError` will mess up the `$delegate` field type
- [`KT-39060`](https://youtrack.jetbrains.com/issue/KT-39060) Kapt: correctErrorTypes don't retain return type of getter in Java stub
- [`KT-39715`](https://youtrack.jetbrains.com/issue/KT-39715) KaptGenerateStubsTask resolves annotation processor options too early (before execution time)
- [`KT-41581`](https://youtrack.jetbrains.com/issue/KT-41581) Kapt doesn't have line breaks between warnings
- [`KT-43804`](https://youtrack.jetbrains.com/issue/KT-43804) Kapt fails to preserve parameter names in open suspend functions
- [`KT-43686`](https://youtrack.jetbrains.com/issue/KT-43686) KaptWithoutKotlincTask should use `@CompileClasspath` for `kotlinStdlibClasspath` for cache relocateability.
- [`KT-45032`](https://youtrack.jetbrains.com/issue/KT-45032) Kapt: NullPointerException: insnList.first must not be null
- [`KT-46176`](https://youtrack.jetbrains.com/issue/KT-46176) Kapt: "java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 3" with delegation and property reference
## 1.5.10
### Compiler

View File

@@ -25,7 +25,6 @@ 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
@@ -155,7 +154,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, PsiHandlingMode.COMPILER)
val builder = RawFirBuilder(session, firProvider.kotlinScopeProvider)
val totalTransformer = FirTotalResolveProcessor(session)
val firFile = builder.buildFirFile(file).also(firProvider::recordFile)

View File

@@ -118,7 +118,7 @@ class ChangesCollector {
storage[packageProtoKey?.let { FqName(it) } ?: fqName] = newData
}
}
} else if (oldData != null) {
} else {
when (oldData) {
is ClassProtoData -> {
removed.add(oldData.nameResolver.getClassId(oldData.proto.fqName).asSingleFqName())

View File

@@ -1,76 +0,0 @@
/*
* 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

@@ -16,7 +16,6 @@
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
@@ -34,8 +33,6 @@ 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
@@ -49,39 +46,31 @@ open class LookupStorage(
@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
@@ -92,8 +81,8 @@ open class LookupStorage(
val key = LookupSymbolKey(lookupSymbol.name, lookupSymbol.scope)
val paths = lookups[lookupSymbol]
val fileIds = paths.mapTo(TreeSet()) { pathToId[it]!! }
lookupMap.append(key, fileIds)
fileIds.addAll(lookupMap[key] ?: emptySet())
lookupMap[key] = fileIds
}
}
@@ -103,6 +92,7 @@ open class LookupStorage(
val id = fileToId[file] ?: continue
idToFile.remove(id)
fileToId.remove(file)
deletedCount++
}
}
@@ -113,6 +103,7 @@ open class LookupStorage(
}
size = 0
deletedCount = 0
super.clean()
}
@@ -120,15 +111,18 @@ 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")
countersFile.writeText("$size\n$deletedCount")
}
} finally {
}
finally {
super.flush(memoryCachesOnly)
}
}
@@ -143,7 +137,13 @@ open class LookupStorage(
return id
}
private fun removeGarbageForTests() {
private fun removeGarbageIfNeeded(force: Boolean = false) {
if (force || (size > MINIMUM_GARBAGE_COLLECTIBLE_SIZE && deletedCount.toDouble() / size > DELETED_TO_SIZE_TRESHOLD)) {
doRemoveGarbage()
}
}
private fun doRemoveGarbage() {
for (hash in lookupMap.keys) {
lookupMap[hash] = lookupMap[hash]!!.filter { it in idToFile }.toSet()
}
@@ -153,6 +153,7 @@ 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)
@@ -164,16 +165,15 @@ open class LookupStorage(
if (fileIds.isEmpty()) {
lookupMap.remove(lookup)
} else {
}
else {
lookupMap[lookup] = fileIds
}
}
}
@TestOnly
fun forceGC() {
removeGarbageForTests()
@TestOnly fun forceGC() {
removeGarbageIfNeeded(force = true)
flush(false)
}

View File

@@ -1104,11 +1104,6 @@ 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
}
@@ -2358,10 +2353,6 @@ 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

@@ -27,10 +27,6 @@ class LookupMap(storage: File) : BasicMap<LookupSymbolKey, Collection<Int>>(stor
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

@@ -3443,34 +3443,6 @@ 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}
@@ -3576,19 +3548,6 @@ 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) {
@@ -3725,48 +3684,11 @@ 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() {
@@ -3793,9 +3715,6 @@ public final class DebugJvmProtoBuf {
if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeMessage(4, setter_);
}
if (((bitField0_ & 0x00000010) == 0x00000010)) {
output.writeMessage(5, delegateMethod_);
}
getUnknownFields().writeTo(output);
}
@@ -3821,10 +3740,6 @@ 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;
@@ -3938,7 +3853,6 @@ public final class DebugJvmProtoBuf {
getSyntheticMethodFieldBuilder();
getGetterFieldBuilder();
getSetterFieldBuilder();
getDelegateMethodFieldBuilder();
}
}
private static Builder create() {
@@ -3971,12 +3885,6 @@ 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;
}
@@ -4037,14 +3945,6 @@ 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;
@@ -4073,9 +3973,6 @@ public final class DebugJvmProtoBuf {
if (other.hasSetter()) {
mergeSetter(other.getSetter());
}
if (other.hasDelegateMethod()) {
mergeDelegateMethod(other.getDelegateMethod());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -4603,167 +4500,6 @@ 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)
}
@@ -5004,7 +4740,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\"\212\003\n\024JvmPropertySi" +
"\030\001\022\022\n\004desc\030\002 \001(\005B\004\230\265\030\001\"\272\002\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" +
@@ -5012,13 +4748,11 @@ 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" +
@@ -5026,9 +4760,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" +
@@ -5036,9 +4770,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" +
@@ -5046,7 +4780,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 =
@@ -5092,7 +4826,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", "DelegateMethod", });
new java.lang.String[] { "Field", "SyntheticMethod", "Getter", "Setter", });
constructorSignature.internalInit(descriptor.getExtensions().get(0));
methodSignature.internalInit(descriptor.getExtensions().get(1));
lambdaClassOriginName.internalInit(descriptor.getExtensions().get(2));

View File

@@ -153,6 +153,7 @@ if (!project.hasProperty("versions.kotlin-native")) {
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
@@ -474,6 +475,10 @@ allprojects {
kotlinOptions {
freeCompilerArgs = commonCompilerArgs + jvmCompilerArgs
if (useJvmIrBackend) {
useIR = true
}
if (useJvmFir && this@allprojects.path !in projectsWithDisabledFirBootstrap) {
freeCompilerArgs += "-Xuse-fir"
freeCompilerArgs += "-Xabi-stability=stable"
@@ -734,6 +739,14 @@ tasks {
dependsOn(":kotlin-scripting-jsr223-test:embeddableTest")
dependsOn(":kotlin-main-kts-test:test")
dependsOn(":kotlin-main-kts-test:testWithIr")
if (kotlinBuildProperties.getOrNull("attachedIntellijVersion") == null &&
!kotlinBuildProperties.getBoolean("disableKotlinPluginModules", false)
) {
dependsOn(":kotlin-scripting-ide-services-test:test")
dependsOn(":kotlin-scripting-ide-services-test:embeddableTest")
}
dependsOn(":kotlin-scripting-js-test:test")
}
@@ -1128,13 +1141,3 @@ plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin:
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

@@ -1,144 +0,0 @@
/*
* 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

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

View File

@@ -17,11 +17,16 @@
// 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 =
@@ -141,4 +146,70 @@ fun ModuleDependency.includeIntellijCoreJarDependencies(project: Project, jarsFi
rootProject = project.rootProject
)
fun Project.intellijRootDir() = IntellijRootUtils.getIntellijRootDir(project)
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()
}
}

View File

@@ -11,7 +11,6 @@ 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
@@ -52,7 +51,7 @@ class CallBasedArgumentGenerator(
callGenerator.putValueIfNeeded(
getJvmKotlinType(i),
StackValue.createDefaultValue(valueParameterTypes[i]),
if (InlineUtil.isInlineParameter(valueParameters[i])) ValueKind.DEFAULT_INLINE_PARAMETER else ValueKind.DEFAULT_PARAMETER,
ValueKind.DEFAULT_PARAMETER,
i
)
}

View File

@@ -15,9 +15,9 @@ enum class ValueKind {
GENERAL,
GENERAL_VARARG,
DEFAULT_PARAMETER,
DEFAULT_INLINE_PARAMETER,
DEFAULT_MASK,
METHOD_HANDLE_IN_DEFAULT,
CAPTURED,
NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND,
NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER
}

View File

@@ -27,16 +27,24 @@ 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;
@@ -44,6 +52,7 @@ 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;
@@ -125,6 +134,11 @@ 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());
@@ -148,6 +162,26 @@ 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

@@ -136,6 +136,8 @@ class CoroutineTransformerMethodVisitor(
UninitializedStoresProcessor(methodNode, shouldPreserveClassInitialization).run()
updateLvtAccordingToLiveness(methodNode, isForNamedFunction)
val spilledToVariableMapping = spillVariables(suspensionPoints, methodNode)
val suspendMarkerVarIndex = methodNode.maxLocals++
@@ -192,8 +194,6 @@ class CoroutineTransformerMethodVisitor(
dropUnboxInlineClassMarkers(methodNode, suspensionPoints)
methodNode.removeEmptyCatchBlocks()
updateLvtAccordingToLiveness(methodNode, isForNamedFunction)
if (languageVersionSettings.isReleaseCoroutines()) {
writeDebugMetadata(methodNode, suspensionPointLineNumbers, spilledToVariableMapping)
}
@@ -791,30 +791,19 @@ class CoroutineTransformerMethodVisitor(
// Mutate method node
fun generateSpillAndUnspill(suspension: SuspensionPoint, slot: Int, spillableVariable: SpillableVariable?) {
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
)
)
if (spillableVariable == null) {
with(instructions) {
insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter {
aconst(null)
store(slot, AsmTypes.OBJECT_TYPE)
})
}
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()
@@ -828,19 +817,6 @@ 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 {
@@ -870,7 +846,25 @@ class CoroutineTransformerMethodVisitor(
})
}
splitLvtRecord(local, localRestart)
// 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
)
)
}
}
fun cleanUpField(suspension: SuspensionPoint, fieldIndex: Int) {
@@ -1260,9 +1254,6 @@ 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.
*
@@ -1297,6 +1288,9 @@ 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
@@ -1304,6 +1298,7 @@ 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
@@ -1315,7 +1310,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 || lvtRecord.name == SUSPEND_CALL_RESULT_NAME) continue
if (lvtRecord.name == CONTINUATION_VARIABLE_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
@@ -1342,32 +1337,14 @@ 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)
method.localVariables.add(node)
if (lvtRecord !in oldLvtNodeToLatestNewLvtNode) {
method.localVariables.add(node)
}
oldLvtNodeToLatestNewLvtNode[lvtRecord] = 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

@@ -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.toArray()
val reachableReturnsIndices = Array(insns.size) init@{ index ->
val insns = methodNode.instructions
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 insns.indices.reversed()) {
for (index in 0 until insns.size()) {
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)
if (methodNode.instructions.toArray().none { it.opcode == Opcodes.NEW })
return
val frames = CustomFramesMethodAnalyzer("fake", methodNode, interpreter, this::UninitializedNewValueFrame).analyze()
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,7 +138,10 @@ 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
@@ -171,10 +174,11 @@ 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"
@@ -184,8 +188,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')"
}
@@ -232,8 +236,7 @@ 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

@@ -295,6 +295,7 @@ class AnonymousObjectTransformer(
capturedBuilder: ParametersBuilder,
isConstructor: Boolean
): InlineResult {
val typeParametersToReify = inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode)
val parameters =
if (isConstructor) capturedBuilder.buildParameters() else getMethodParametersWithCaptured(capturedBuilder, sourceNode)
@@ -303,10 +304,7 @@ class AnonymousObjectTransformer(
transformationInfo.capturedLambdasToInline, parentRemapper, isConstructor
)
val reifiedTypeParametersUsages = if (inliningContext.shouldReifyTypeParametersInObjects)
inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode)
else null
val result = MethodInliner(
val inliner = MethodInliner(
sourceNode,
parameters,
inliningContext.subInline(transformationInfo.nameGenerator),
@@ -321,8 +319,10 @@ class AnonymousObjectTransformer(
inliningContext.callSiteInfo.file,
inliningContext.callSiteInfo.lineNumber
), null
).doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf())
reifiedTypeParametersUsages?.let(result.reifiedTypeParametersUsages::mergeAll)
)
val result = inliner.doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf())
result.reifiedTypeParametersUsages.mergeAll(typeParametersToReify)
deferringVisitor.visitMaxs(-1, -1)
return result
}
@@ -421,13 +421,11 @@ class AnonymousObjectTransformer(
}
private fun getMethodParametersWithCaptured(capturedBuilder: ParametersBuilder, sourceNode: MethodNode): Parameters {
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)
}
val builder = ParametersBuilder.initializeBuilderFrom(
oldObjectType,
sourceNode.desc,
isStatic = sourceNode.access and Opcodes.ACC_STATIC != 0
)
for (param in capturedBuilder.listCaptured()) {
builder.addCapturedParamCopy(param)
}

View File

@@ -33,9 +33,9 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
protected val invocationParamBuilder = ParametersBuilder.newBuilder()
protected val expressionMap = linkedMapOf<Int, FunctionalArgument>()
private val maskValues = ArrayList<Int>()
private var maskStartIndex = -1
private var methodHandleInDefaultMethodIndex = -1
protected val maskValues = ArrayList<Int>()
protected var maskStartIndex = -1
protected var methodHandleInDefaultMethodIndex = -1
protected fun generateStub(text: String, codegen: BaseExpressionCodegen) {
leaveTemps()
@@ -71,25 +71,14 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
private fun inlineCall(nodeAndSmap: SMAPAndMethodNode, isInlineOnly: Boolean): InlineResult {
val node = nodeAndSmap.node
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) {
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 (lambda.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
}
rememberCapturedForDefaultLambda(lambda)
}
}
@@ -147,6 +136,16 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
return result
}
abstract fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda>
protected inline fun <T> extractDefaultLambdas(
node: MethodNode, parameters: Map<Int, T>, block: ExtractedDefaultLambda.(T) -> DefaultLambda
): List<DefaultLambda> = expandMaskConditionsAndUpdateVariableNodes(
node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex, parameters.keys
).map {
it.block(parameters[it.offset]!!)
}
private fun generateAndInsertFinallyBlocks(
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
@@ -239,12 +238,10 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
NonInlineableArgumentForInlineableParameterCalledInSuspend
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER ->
NonInlineableArgumentForInlineableSuspendParameter
ValueKind.DEFAULT_INLINE_PARAMETER ->
DefaultValueOfInlineParameter
else -> null
}
when {
kind === ValueKind.DEFAULT_PARAMETER || kind === ValueKind.DEFAULT_INLINE_PARAMETER ->
kind === ValueKind.DEFAULT_PARAMETER ->
codegen.frameMap.enterTemp(info.type) // the inline function will put the value into this slot
stackValue.isLocalWithNoBoxing(jvmKotlinType) ->
info.remapValue = stackValue
@@ -263,6 +260,14 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
}
}
private fun rememberCapturedForDefaultLambda(defaultLambda: DefaultLambda) {
for (captured in defaultLambda.capturedVars) {
val info = invocationParamBuilder.addCapturedParam(captured, captured.fieldName, false)
info.remapValue = StackValue.local(codegen.frameMap.enterTemp(info.type), info.type)
info.isSynthetic = true
}
}
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

View File

@@ -44,16 +44,8 @@ open class InliningContext(
val lambdaInfo: LambdaInfo?,
val classRegeneration: Boolean
) {
val isInliningLambda
get() = 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
val isInliningLambda = lambdaInfo != null
var generateAssertField = false
@@ -62,8 +54,7 @@ open class InliningContext(
var isContinuation: Boolean = false
val isRoot: Boolean
get() = parent == null
val isRoot: Boolean = parent == null
val root: RootInliningContext
get() = if (isRoot) this as RootInliningContext else parent!!.root

View File

@@ -6,7 +6,6 @@
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.org.objectweb.asm.ClassReader
@@ -18,6 +17,10 @@ import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
interface FunctionalArgument
abstract class LambdaInfo : FunctionalArgument {
abstract val isBoundCallableReference: Boolean
abstract val isSuspend: Boolean
abstract val lambdaClassType: Type
abstract val invokeMethod: Method
@@ -35,17 +38,11 @@ abstract class LambdaInfo : FunctionalArgument {
val reifiedTypeParametersUsages = ReifiedTypeParametersUsages()
open val hasDispatchReceiver
get() = true
open val hasDispatchReceiver = true
fun addAllParameters(remapper: FieldRemapper): Parameters {
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)
}
val builder = ParametersBuilder.initializeBuilderFrom(OBJECT_TYPE, invokeMethod.descriptor, this)
for (info in capturedVars) {
val field = remapper.findField(FieldInsnNode(0, info.containingLambdaName, info.fieldName, ""))
?: error("Captured field not found: " + info.containingLambdaName + "." + info.fieldName)
@@ -67,7 +64,6 @@ abstract class LambdaInfo : FunctionalArgument {
object NonInlineableArgumentForInlineableParameterCalledInSuspend : FunctionalArgument
object NonInlineableArgumentForInlineableSuspendParameter : FunctionalArgument
object DefaultValueOfInlineParameter : FunctionalArgument
abstract class ExpressionLambda : LambdaInfo() {
fun generateLambdaBody(sourceCompiler: SourceCompilerForInline) {
@@ -76,64 +72,67 @@ abstract class ExpressionLambda : LambdaInfo() {
}
}
class DefaultLambda(info: ExtractedDefaultLambda, sourceCompiler: SourceCompilerForInline) : LambdaInfo() {
val isBoundCallableReference: Boolean
abstract class DefaultLambda(
final override val lambdaClassType: Type,
capturedArgs: Array<Type>,
val offset: Int,
val needReification: Boolean,
sourceCompiler: SourceCompilerForInline
) : LambdaInfo() {
final override val isSuspend
get() = false // TODO: it should probably be true sometimes, but it never was
final override val isBoundCallableReference: Boolean
final override val capturedVars: List<CapturedParamDesc>
override val lambdaClassType: Type = info.type
override val capturedVars: List<CapturedParamDesc>
override val invokeMethod: Method
final override val invokeMethod: Method
get() = Method(node.node.name, node.node.desc)
private val nullableAnyType = sourceCompiler.state.module.builtIns.nullableAnyType
override val invokeMethodParameters: List<KotlinType>
get() = List(invokeMethod.argumentTypes.size) { nullableAnyType }
override val invokeMethodReturnType: KotlinType
get() = nullableAnyType
val originalBoundReceiverType: Type?
protected val isPropertyReference: Boolean
protected val isFunctionReference: Boolean
init {
val classBytes =
sourceCompiler.state.inlineCache.classBytes.getOrPut(lambdaClassType.internalName) {
loadClassBytesByInternalName(sourceCompiler.state, lambdaClassType.internalName)
}
val classBytes = loadClass(sourceCompiler)
val superName = ClassReader(classBytes).superName
// 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"
}
isPropertyReference = superName in PROPERTY_REFERENCE_SUPER_CLASSES
isFunctionReference = superName == FUNCTION_REFERENCE.internalName || superName == FUNCTION_REFERENCE_IMPL.internalName
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 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"
}
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) }
capturedArgs.singleOrNull()?.takeIf { (isFunctionReference || isPropertyReference) && AsmUtil.isPrimitive(it) }
capturedVars =
if (isReference)
info.capturedArgs.singleOrNull()?.let {
// See `InlinedLambdaRemapper`
listOf(capturedParamDesc(AsmUtil.RECEIVER_PARAMETER_NAME, OBJECT_TYPE, isSuspend = false))
if (isFunctionReference || isPropertyReference)
capturedArgs.singleOrNull()?.let {
listOf(capturedParamDesc(AsmUtil.RECEIVER_PARAMETER_NAME, AsmUtil.boxType(it), isSuspend = false))
} ?: emptyList()
else
constructor?.findCapturedFieldAssignmentInstructions()?.map { fieldNode ->
capturedParamDesc(fieldNode.name, Type.getType(fieldNode.desc), isSuspend = false)
}?.toList() ?: emptyList()
isBoundCallableReference = isReference && capturedVars.isNotEmpty()
node = loadDefaultLambdaBody(classBytes, lambdaClassType, isPropertyReference)
isBoundCallableReference = (isFunctionReference || isPropertyReference) && capturedVars.isNotEmpty()
}
private fun loadClass(sourceCompiler: SourceCompilerForInline): ByteArray =
sourceCompiler.state.inlineCache.classBytes.getOrPut(lambdaClassType.internalName) {
loadClassBytesByInternalName(sourceCompiler.state, lambdaClassType.internalName)
}
// Returns whether the loaded invoke is erased, i.e. the name equals the fallback and all types are `Object`.
protected fun loadInvoke(sourceCompiler: SourceCompilerForInline, erasedName: String, actualMethod: Method): Boolean {
val classBytes = loadClass(sourceCompiler)
// TODO: `signatureAmbiguity = true` ignores the argument types from `invokeMethod` and only looks at the count.
node = getMethodNode(classBytes, actualMethod.name, actualMethod.descriptor, lambdaClassType, signatureAmbiguity = true)
?: getMethodNode(classBytes, erasedName, actualMethod.descriptor, lambdaClassType, signatureAmbiguity = true)
?: error("Can't find method '$actualMethod' in '${lambdaClassType.internalName}'")
return invokeMethod.run { name == erasedName && returnType == OBJECT_TYPE && argumentTypes.all { it == OBJECT_TYPE } }
}
private companion object {

View File

@@ -17,8 +17,8 @@ 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.*
import org.jetbrains.kotlin.codegen.optimization.fixStack.FastStackAnalyzer
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
import org.jetbrains.kotlin.config.LanguageFeature
@@ -36,6 +36,8 @@ 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.*
@@ -55,10 +57,8 @@ 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()
@@ -92,6 +92,10 @@ 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()
@@ -228,7 +232,7 @@ class MethodInliner(
val expectedParameters = info.invokeMethod.argumentTypes
val expectedKotlinParameters = info.invokeMethodParameters
val argumentCount = Type.getArgumentTypes(desc).size.let {
if (info is PsiExpressionLambda && info.invokeMethodDescriptor.isSuspend && it < expectedParameters.size) {
if (!inliningContext.root.state.isIrBackend && info.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)
@@ -273,8 +277,7 @@ 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)
@@ -304,7 +307,7 @@ class MethodInliner(
} else capturedParamDesc
visitFieldInsn(
Opcodes.GETSTATIC, realDesc.containingLambdaName,
foldName(realDesc.fieldName), realDesc.type.descriptor
FieldRemapper.foldName(realDesc.fieldName), realDesc.type.descriptor
)
}
super.visitMethodInsn(opcode, info.newClassName, name, info.newConstructorDescriptor, itf)
@@ -318,11 +321,10 @@ class MethodInliner(
} else {
super.visitMethodInsn(opcode, owner, name, desc, itf)
}
} 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 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 {
super.visitMethodInsn(opcode, owner, name, desc, itf)
}
@@ -347,6 +349,9 @@ 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()
@@ -376,7 +381,10 @@ class MethodInliner(
private fun getNewIndex(`var`: Int): Int {
val lambdaInfo = inliningContext.lambdaInfo
if (reorderIrLambdaParameters && lambdaInfo is IrExpressionLambda) {
val extensionSize = if (lambdaInfo.isExtensionLambda) lambdaInfo.invokeMethod.argumentTypes[0].size else 0
val extensionSize =
if (lambdaInfo.isExtensionLambda && !lambdaInfo.isBoundCallableReference)
lambdaInfo.invokeMethod.argumentTypes[0].size
else 0
return when {
// v-- extensionSize v-- argsSizeOnStack
// |- extension -|- captured -|- real -|- locals -| old descriptor
@@ -442,7 +450,7 @@ class MethodInliner(
else -> ""
}
val varName = if (varSuffix.isNotEmpty() && name == AsmUtil.THIS) AsmUtil.INLINE_DECLARATION_SITE_THIS else name
val varName = if (!varSuffix.isEmpty() && name == AsmUtil.THIS) AsmUtil.INLINE_DECLARATION_SITE_THIS else name
super.visitLocalVariable(varName + varSuffix, desc, signature, start, end, getNewIndex(index))
}
}
@@ -534,37 +542,33 @@ class MethodInliner(
cur.opcode == Opcodes.GETSTATIC -> {
val fieldInsnNode = cur as FieldInsnNode?
val className = fieldInsnNode!!.owner
when {
isAnonymousSingletonLoad(className, fieldInsnNode.name) -> {
recordTransformation(
AnonymousObjectTransformationInfo(
className, awaitClassReification, isAlreadyRegenerated(className), true,
inliningContext.nameGenerator
)
if (isAnonymousSingletonLoad(className, fieldInsnNode.name)) {
recordTransformation(
AnonymousObjectTransformationInfo(
className, awaitClassReification, isAlreadyRegenerated(className), true,
inliningContext.nameGenerator
)
awaitClassReification = false
}
isWhenMappingAccess(className, fieldInsnNode.name) -> {
recordTransformation(
WhenMappingTransformationInfo(
className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode
)
)
awaitClassReification = false
} else if (isWhenMappingAccess(className, fieldInsnNode.name)) {
recordTransformation(
WhenMappingTransformationInfo(
className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode
)
}
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
}
)
} else if (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
}
}
@@ -593,7 +597,7 @@ class MethodInliner(
assert(lambdaInfo.lambdaClassType.internalName == nodeRemapper.originalLambdaInternalName) {
"Wrong bytecode template for contract template: ${lambdaInfo.lambdaClassType.internalName} != ${nodeRemapper.originalLambdaInternalName}"
}
fieldInsn.name = foldName(fieldInsn.name)
fieldInsn.name = FieldRemapper.foldName(fieldInsn.name)
fieldInsn.opcode = Opcodes.PUTSTATIC
toDelete.addAll(stackTransformations)
}
@@ -633,8 +637,9 @@ 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 !is PsiExpressionLambda || !lambdaInfo.invokeMethodDescriptor.isSuspend) return
if (!lambdaInfo.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 }
@@ -747,7 +752,7 @@ class MethodInliner(
ApiVersionCallsPreprocessingMethodTransformer(targetApiVersion).transform("fake", node)
}
val frames = FastStackAnalyzer("<fake>", node, FixStackInterpreter()).analyze()
val frames = analyzeMethodNodeWithInterpreter(node, BasicInterpreter())
val localReturnsNormalizer = LocalReturnsNormalizer()
@@ -836,9 +841,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.associate {
val map = capturedVars.map {
offset to it.also { offset += it.type.size }
}
}.toMap()
var cur: AbstractInsnNode? = node.instructions.first
while (cur != null) {
@@ -883,7 +888,6 @@ class MethodInliner(
}
}
@Suppress("SameParameterValue")
private fun wrapException(originalException: Throwable, node: MethodNode, errorSuffix: String): RuntimeException {
return if (originalException is InlineException) {
InlineException("$errorPrefix: $errorSuffix", originalException)
@@ -896,7 +900,7 @@ class MethodInliner(
private class LocalReturn(
private val returnInsn: AbstractInsnNode,
private val insertBeforeInsn: AbstractInsnNode,
private val frame: Frame<FixStackValue>
private val frame: Frame<BasicValue>
) {
fun transform(insnList: InsnList, returnVariableIndex: Int) {
@@ -907,19 +911,22 @@ class MethodInliner(
if (expectedStackSize == actualStackSize) return
var stackSize = actualStackSize
val topValue = frame.getStack(stackSize - 1)
if (isReturnWithValue) {
insnList.insertBefore(insertBeforeInsn, VarInsnNode(topValue.storeOpcode, returnVariableIndex))
val storeOpcode = Opcodes.ISTORE + returnInsn.opcode - Opcodes.IRETURN
insnList.insertBefore(insertBeforeInsn, VarInsnNode(storeOpcode, returnVariableIndex))
stackSize--
}
while (stackSize > 0) {
insnList.insertBefore(insertBeforeInsn, InsnNode(frame.getStack(stackSize - 1).popOpcode))
val stackElementSize = frame.getStack(stackSize - 1).size
val popOpcode = if (stackElementSize == 1) Opcodes.POP else Opcodes.POP2
insnList.insertBefore(insertBeforeInsn, InsnNode(popOpcode))
stackSize--
}
if (isReturnWithValue) {
insnList.insertBefore(insertBeforeInsn, VarInsnNode(topValue.loadOpcode, returnVariableIndex))
val loadOpcode = Opcodes.ILOAD + returnInsn.opcode - Opcodes.IRETURN
insnList.insertBefore(insertBeforeInsn, VarInsnNode(loadOpcode, returnVariableIndex))
}
}
}
@@ -929,10 +936,10 @@ class MethodInliner(
private var returnVariableSize = 0
private var returnOpcode = -1
fun addLocalReturnToTransform(
internal fun addLocalReturnToTransform(
returnInsn: AbstractInsnNode,
insertBeforeInsn: AbstractInsnNode,
sourceValueFrame: Frame<FixStackValue>
sourceValueFrame: Frame<BasicValue>
) {
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] }
@@ -941,7 +948,11 @@ 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

@@ -10,6 +10,7 @@ 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,6 +18,15 @@ 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)

View File

@@ -107,5 +107,22 @@ 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,13 +5,16 @@
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.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
@@ -25,9 +28,12 @@ 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.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,
@@ -89,7 +95,8 @@ class PsiInlineCodegen(
private val hiddenParameters = mutableListOf<Pair<ParameterInfo, Int>>()
override fun processHiddenParameters() {
if (!DescriptorAsmUtil.isStaticMethod((sourceCompiler as PsiSourceCompilerForInline).context.contextKind, functionDescriptor)) {
val contextKind = (sourceCompiler as PsiSourceCompilerForInline).context.contextKind
if (getMethodAsmFlags(functionDescriptor, contextKind, state) and Opcodes.ACC_STATIC == 0) {
hiddenParameters += invocationParamBuilder.addNextParameter(methodOwner, false, actualDispatchReceiver) to
codegen.frameMap.enterTemp(methodOwner)
}
@@ -111,6 +118,14 @@ class PsiInlineCodegen(
hiddenParameters.clear()
}
/*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)
}
override fun genValueAndPut(
valueParameterDescriptor: ValueParameterDescriptor?,
argumentExpression: KtExpression,
@@ -122,9 +137,7 @@ class PsiInlineCodegen(
"which cannot be declared in Kotlin and thus be inline: $codegen"
}
val isInlineParameter = InlineUtil.isInlineParameter(valueParameterDescriptor)
//TODO deparenthesize typed
if (isInlineParameter && isInlinableParameterExpression(KtPsiUtil.deparenthesize(argumentExpression))) {
if (isInliningParameter(argumentExpression, valueParameterDescriptor)) {
rememberClosure(argumentExpression, parameterType.type, valueParameterDescriptor)
} else {
val value = codegen.gen(argumentExpression)
@@ -185,6 +198,11 @@ class PsiInlineCodegen(
putCapturedToLocalVal(stackValue, activeLambda!!.capturedVars[paramIndex], stackValue.kotlinType)
override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>) = Unit
override fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda> =
extractDefaultLambdas(node, extractDefaultLambdaOffsetAndDescriptor(jvmSignature, functionDescriptor)) { parameter ->
PsiDefaultLambda(type, capturedArgs, parameter, offset, needReification, sourceCompiler)
}
}
private val FunctionDescriptor.explicitParameters
@@ -194,7 +212,7 @@ class PsiExpressionLambda(
expression: KtExpression,
private val state: GenerationState,
val isCrossInline: Boolean,
val isBoundCallableReference: Boolean
override val isBoundCallableReference: Boolean
) : ExpressionLambda() {
override val lambdaClassType: Type
@@ -204,7 +222,7 @@ class PsiExpressionLambda(
override val invokeMethodParameters: List<KotlinType?>
get() {
val actualInvokeDescriptor = if (invokeMethodDescriptor.isSuspend)
val actualInvokeDescriptor = if (isSuspend)
getOrCreateJvmSuspendFunctionView(invokeMethodDescriptor, state)
else
invokeMethodDescriptor
@@ -222,6 +240,8 @@ class PsiExpressionLambda(
override val returnLabels: Map<String, Label?>
override val isSuspend: Boolean
val closure: CalculatedClosure
init {
@@ -250,6 +270,7 @@ class PsiExpressionLambda(
?: throw AssertionError("null closure for lambda ${expression.text}")
returnLabels = getDeclarationLabels(expression, invokeMethodDescriptor).associateWith { null }
invokeMethod = state.typeMapper.mapAsmMethod(invokeMethodDescriptor)
isSuspend = invokeMethodDescriptor.isSuspend
}
// This can only be computed after generating the body, hence `lazy`.
@@ -280,3 +301,32 @@ class PsiExpressionLambda(
val isPropertyReference: Boolean
get() = propertyReferenceInfo != null
}
class PsiDefaultLambda(
lambdaClassType: Type,
capturedArgs: Array<Type>,
parameterDescriptor: ValueParameterDescriptor,
offset: Int,
needReification: Boolean,
sourceCompiler: SourceCompilerForInline
) : DefaultLambda(lambdaClassType, capturedArgs, offset, needReification, sourceCompiler) {
private val invokeMethodDescriptor: FunctionDescriptor
override val invokeMethodParameters: List<KotlinType?>
get() = invokeMethodDescriptor.explicitParameters.map { it.returnType }
override val invokeMethodReturnType: KotlinType?
get() = invokeMethodDescriptor.returnType
init {
val name = if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE
val descriptor = parameterDescriptor.type.memberScope
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND)
.single()
.let { if (parameterDescriptor.type.isSuspendFunctionType) getOrCreateJvmSuspendFunctionView(it, sourceCompiler.state) else it }
// This is technically wrong as it always uses `invoke`, but `loadInvoke` will fall back to `get` which is never mangled...
val asmMethod = sourceCompiler.state.typeMapper.mapAsmMethod(descriptor)
val invokeIsErased = loadInvoke(sourceCompiler, name.asString(), asmMethod)
invokeMethodDescriptor = if (invokeIsErased) descriptor.original else descriptor
}
}

View File

@@ -78,12 +78,12 @@ fun loadCompiledInlineFunction(
state: GenerationState
): SMAPAndMethodNode {
val containerType = AsmUtil.asmTypeByClassId(containerId)
val bytes = state.inlineCache.classBytes.getOrPut(containerType.internalName) {
findVirtualFile(state, containerId)?.contentsToByteArray()
?: throw IllegalStateException("Couldn't find declaration file for $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)
getMethodNode(containerType, bytes, asmMethod.name, asmMethod.descriptor, isSuspend, isMangled)
}
return SMAPAndMethodNode(cloneMethodNode(resultInCache.node), resultInCache.classSMAP)
}
@@ -91,24 +91,25 @@ fun loadCompiledInlineFunction(
private fun getMethodNode(
owner: Type,
bytes: ByteArray,
method: Method,
name: String,
descriptor: String,
isSuspend: Boolean,
isMangled: Boolean
): SMAPAndMethodNode {
getMethodNode(owner, bytes, method, isSuspend)?.let { return it }
getMethodNode(owner, bytes, name, descriptor, 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 }
val dashIndex = name.indexOf('-')
val nameWithoutManglingSuffix = if (dashIndex > 0) name.substring(0, dashIndex) else name
if (nameWithoutManglingSuffix != name) {
getMethodNode(owner, bytes, nameWithoutManglingSuffix, descriptor, isSuspend)?.let { return it }
}
getMethodNode(owner, bytes, Method("$nameWithoutManglingSuffix-impl", method.descriptor), isSuspend)?.let { return it }
getMethodNode(owner, bytes, "$nameWithoutManglingSuffix-impl", descriptor, isSuspend)?.let { return it }
}
throw IllegalStateException("couldn't find inline method $owner.$method")
throw IllegalStateException("couldn't find inline method $owner.$name$descriptor")
}
// 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)
private fun getMethodNode(owner: Type, bytes: ByteArray, name: String, descriptor: String, isSuspend: Boolean) =
(if (isSuspend) getMethodNode(bytes, name + FOR_INLINE_SUFFIX, descriptor, owner) else null)
?: getMethodNode(bytes, name, descriptor, owner)

View File

@@ -16,16 +16,20 @@
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.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.util.OperatorNameConventions
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.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,
@@ -37,6 +41,25 @@ 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
return functionDescriptor.valueParameters.filter {
InlineUtil.isInlineParameter(it) && it.declaresDefaultValue()
}.associateBy {
parameterOffsets[valueParameterOffset + it.index]
}
}
class ExtractedDefaultLambda(val type: Type, val capturedArgs: Array<Type>, val offset: Int, val needReification: Boolean)
fun expandMaskConditionsAndUpdateVariableNodes(
@@ -179,68 +202,3 @@ 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,7 +43,6 @@ 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
@@ -85,18 +84,40 @@ 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 inline fun getMethodNode(classData: ByteArray, classType: Type, crossinline match: (Method) -> Boolean): SMAPAndMethodNode? {
internal fun getMethodNode(
classData: ByteArray,
methodName: String,
methodDescriptor: String,
classType: Type,
signatureAmbiguity: Boolean = false
): SMAPAndMethodNode? {
val cr = ClassReader(classData)
var node: MethodNode? = null
var sourceFile: String? = null
var sourceMap: String? = null
ClassReader(classData).accept(object : ClassVisitor(Opcodes.API_VERSION) {
val debugInfo = arrayOfNulls<String>(2)
cr.accept(object : ClassVisitor(Opcodes.API_VERSION) {
override fun visitSource(source: String?, debug: String?) {
sourceFile = source
sourceMap = debug
super.visitSource(source, debug)
debugInfo[0] = source
debugInfo[1] = debug
}
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
if (!match(Method(name, desc))) return null
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
}
}
node?.let { existing ->
throw AssertionError("Can't find proper '$name' method for inline: ambiguity between '${existing.name + existing.desc}' and '${name + desc}'")
}
@@ -105,14 +126,14 @@ internal inline fun getMethodNode(classData: ByteArray, classType: Type, crossin
}
}, ClassReader.SKIP_FRAMES or if (GENERATE_SMAP) 0 else ClassReader.SKIP_DEBUG)
return node?.let{
val (first, last) = listOfNotNull(it).lineNumberRange()
SMAPAndMethodNode(it, SMAPParser.parseOrCreateDefault(sourceMap, sourceFile, classType.internalName, first, last))
if (node == null) {
return null
}
}
internal fun getMethodNode(classData: ByteArray, classType: Type, method: Method): SMAPAndMethodNode? =
getMethodNode(classData, classType) { it == method }
val (first, last) = listOfNotNull(node).lineNumberRange()
val smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classType.internalName, first, last)
return SMAPAndMethodNode(node!!, smap)
}
internal fun Collection<MethodNode>.lineNumberRange(): Pair<Int, Int> {
var minLine = Int.MAX_VALUE

View File

@@ -72,30 +72,18 @@ class OptimizationMethodVisitor(
}
companion object {
private const val MEMORY_LIMIT_BY_METHOD_MB = 50
private const val TRY_CATCH_BLOCKS_SOFT_LIMIT = 16
private val MEMORY_LIMIT_BY_METHOD_MB = 50
fun canBeOptimized(node: MethodNode): Boolean {
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
val totalFramesSizeMb = node.instructions.size() * (node.maxLocals + node.maxStack) / (1024 * 1024)
return totalFramesSizeMb < MEMORY_LIMIT_BY_METHOD_MB
}
fun canBeOptimizedUsingSourceInterpreter(node: MethodNode): Boolean {
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
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
}
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(
boxedType: Type,
private val boxedType: Type,
val boxingInsn: AbstractInsnNode,
val progressionIterator: ProgressionIteratorBasicValue?,
val generationState: GenerationState

View File

@@ -38,10 +38,6 @@ 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

@@ -11,8 +11,8 @@ import org.jetbrains.org.objectweb.asm.tree.*
class ControlFlowGraph private constructor(private val insns: InsnList) {
private val successors: Array<MutableList<Int>> = Array(insns.size()) { ArrayList(2) }
private val predecessors: Array<MutableList<Int>> = Array(insns.size()) { ArrayList(2) }
private val successors: Array<MutableList<Int>> = Array(insns.size()) { ArrayList() }
private val predecessors: Array<MutableList<Int>> = Array(insns.size()) { ArrayList() }
fun getSuccessorsIndices(insn: AbstractInsnNode): List<Int> = getSuccessorsIndices(insns.indexOf(insn))
fun getSuccessorsIndices(index: Int): List<Int> = successors[index]

View File

@@ -45,7 +45,7 @@ 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
* @see FlexibleMethodAnalyzer
*/
@Suppress("DuplicatedCode")
open class FastMethodAnalyzer<V : Value>(

View File

@@ -0,0 +1,346 @@
/*
* 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
/**
* This class is a modified version of `org.objectweb.asm.tree.analysis.Analyzer`
*
* @see FastMethodAnalyzer
*
* @author Eric Bruneton
* @author Dmitry Petrov
*/
@Suppress("DuplicatedCode")
open class FlexibleMethodAnalyzer<V : Value>(
private val owner: String,
val method: MethodNode,
protected val interpreter: Interpreter<V>
) {
protected val insnsArray: Array<AbstractInsnNode> = method.instructions.toArray()
private val nInsns = insnsArray.size
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
private val singlePredBlock = IntArray(nInsns)
protected open fun newFrame(nLocals: Int, nStack: Int): Frame<V> = Frame(nLocals, nStack)
protected open fun visitControlFlowEdge(insn: Int, successor: Int): Boolean = true
protected open fun visitControlFlowExceptionEdge(insn: Int, successor: Int): Boolean = true
fun analyze(): Array<Frame<V>?> {
if (nInsns == 0) return frames
checkAssertions()
computeExceptionHandlersForEachInsn()
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()
if (visitControlFlowExceptionEdge(insn, 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 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
}
}
}
private fun AbstractInsnNode.indexOf() = method.instructions.indexOf(this)
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) {
processControlFlowEdge(current, insn, insn + 1)
}
private fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = insnNode.dflt.indexOf()
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 = label.indexOf()
processControlFlowEdge(current, insn, jump)
}
}
private fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = insnNode.dflt.indexOf()
processControlFlowEdge(current, insn, jump)
for (label in insnNode.labels) {
jump = label.indexOf()
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 = insnNode.label.indexOf()
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(insn, 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, 0, current)
}
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 insn = insnsArray[j]
if (!insn.isMeaningful) continue
var insnHandlers: MutableList<TryCatchBlockNode>? = handlers[j]
if (insnHandlers == null) {
insnHandlers = ArrayList<TryCatchBlockNode>()
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
}
}
}

View File

@@ -1,239 +0,0 @@
/*
* 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.fixStack
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
/**
* @see org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
*/
@Suppress("DuplicatedCode")
internal open class FastStackAnalyzer<V : Value>(
private val owner: String,
val method: MethodNode,
protected val interpreter: Interpreter<V>
) {
protected val insnsArray: Array<AbstractInsnNode> = method.instructions.toArray()
private val nInsns = insnsArray.size
private 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)
protected open fun visitControlFlowEdge(insn: Int, successor: Int): Boolean = true
protected open fun visitControlFlowExceptionEdge(insn: Int, successor: Int): Boolean = true
fun analyze(): Array<Frame<V>?> {
if (nInsns == 0) return frames
// This is a very specific version of method bytecode analyzer that doesn't perform any DFA,
// but infers stack types for reachable instructions instead.
checkAssertions()
computeExceptionEdges()
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]
val insnOpcode = insnNode.opcode
val insnType = insnNode.type
try {
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
visitNopInsn(f, insn)
} else {
current.init(f)
if (insnOpcode != Opcodes.RETURN) {
// Don't care about possibly incompatible return type
current.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()
if (visitControlFlowExceptionEdge(insn, tcb.handler.indexOf())) {
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
}
private fun AbstractInsnNode.indexOf() = method.instructions.indexOf(this)
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) {
processControlFlowEdge(current, insn, insn + 1)
}
private fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = insnNode.dflt.indexOf()
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 = label.indexOf()
processControlFlowEdge(current, insn, jump)
}
}
private fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = insnNode.dflt.indexOf()
processControlFlowEdge(current, insn, jump)
for (label in insnNode.labels) {
jump = label.indexOf()
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 = insnNode.label.indexOf()
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)
}
private fun computeExceptionEdges() {
for (tcb in method.tryCatchBlocks) {
// Don't have to visit same exception handler multiple times - we care only about stack state at TCB start.
val start = tcb.start.indexOf()
var insnHandlers: MutableList<TryCatchBlockNode>? = handlers[start]
if (insnHandlers == null) {
insnHandlers = ArrayList()
handlers[start] = insnHandlers
}
insnHandlers.add(tcb)
}
}
private fun mergeControlFlowEdge(dest: Int, frame: Frame<V>) {
val destFrame = frames[dest]
if (destFrame == null) {
// Don't have to visit same instruction multiple times - we care only about "initial" stack state.
frames[dest] = newFrame(frame.locals, frame.maxStackSize).apply { init(frame) }
if (!queued[dest]) {
queued[dest] = true
queue[top++] = dest
}
}
}
}

View File

@@ -19,6 +19,9 @@ package org.jetbrains.kotlin.codegen.optimization.fixStack
import com.intellij.util.containers.Stack
import org.jetbrains.kotlin.codegen.inline.isAfterInlineMarker
import org.jetbrains.kotlin.codegen.inline.isBeforeInlineMarker
import org.jetbrains.kotlin.codegen.inline.isMarkedReturn
import org.jetbrains.kotlin.codegen.optimization.common.FlexibleMethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -26,6 +29,7 @@ import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode
import org.jetbrains.org.objectweb.asm.tree.LabelNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import kotlin.math.max
@@ -45,14 +49,9 @@ internal class FixStackAnalyzer(
val maxExtraStackSize: Int get() = analyzer.maxExtraStackSize
fun getStackToSpill(location: AbstractInsnNode): List<FixStackValue>? =
analyzer.spilledStacks[location]
fun getActualStack(location: AbstractInsnNode): List<FixStackValue>? =
getFrame(location)?.getStackContent()
fun getActualStackSize(location: AbstractInsnNode): Int =
getFrame(location)?.stackSizeWithExtra ?: DEAD_CODE_STACK_SIZE
fun getStackToSpill(location: AbstractInsnNode) = analyzer.spilledStacks[location]
fun getActualStack(location: AbstractInsnNode) = getFrame(location)?.getStackContent()
fun getActualStackSize(location: AbstractInsnNode) = getFrame(location)?.stackSizeWithExtra ?: DEAD_CODE_STACK_SIZE
fun getExpectedStackSize(location: AbstractInsnNode): Int {
// We should look for expected stack size at loop entry point markers if available,
@@ -89,10 +88,8 @@ internal class FixStackAnalyzer(
private val analyzer = InternalAnalyzer(owner)
private inner class InternalAnalyzer(owner: String) :
FastStackAnalyzer<FixStackValue>(owner, method, FixStackInterpreter()) {
val spilledStacks = hashMapOf<AbstractInsnNode, List<FixStackValue>>()
private inner class InternalAnalyzer(owner: String) : FlexibleMethodAnalyzer<BasicValue>(owner, method, OptimizationBasicInterpreter()) {
val spilledStacks = hashMapOf<AbstractInsnNode, List<BasicValue>>()
var maxExtraStackSize = 0; private set
override fun visitControlFlowEdge(insn: Int, successor: Int): Boolean {
@@ -101,15 +98,15 @@ internal class FixStackAnalyzer(
return !(insnNode is JumpInsnNode && context.breakContinueGotoNodes.contains(insnNode))
}
override fun newFrame(nLocals: Int, nStack: Int): Frame<FixStackValue> =
override fun newFrame(nLocals: Int, nStack: Int): Frame<BasicValue> =
FixStackFrame(nLocals, nStack)
private fun indexOf(node: AbstractInsnNode) = method.instructions.indexOf(node)
inner class FixStackFrame(nLocals: Int, nStack: Int) : Frame<FixStackValue>(nLocals, nStack) {
val extraStack = Stack<FixStackValue>()
inner class FixStackFrame(nLocals: Int, nStack: Int) : Frame<BasicValue>(nLocals, nStack) {
val extraStack = Stack<BasicValue>()
override fun init(src: Frame<out FixStackValue>): Frame<FixStackValue> {
override fun init(src: Frame<out BasicValue>): Frame<BasicValue> {
extraStack.clear()
extraStack.addAll((src as FixStackFrame).extraStack)
return super.init(src)
@@ -120,7 +117,7 @@ internal class FixStackAnalyzer(
super.clearStack()
}
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<FixStackValue>) {
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<BasicValue>) {
when {
PseudoInsn.SAVE_STACK_BEFORE_TRY.isa(insn) ->
executeSaveStackBeforeTry(insn)
@@ -130,8 +127,10 @@ internal class FixStackAnalyzer(
executeBeforeInlineCallMarker(insn)
isAfterInlineMarker(insn) ->
executeAfterInlineCallMarker(insn)
insn.opcode == Opcodes.RETURN ->
return
isMarkedReturn(insn) -> {
// KT-9644: might throw "Incompatible return type" on non-local return, in fact we don't care.
if (insn.opcode == Opcodes.RETURN) return
}
}
super.execute(insn, interpreter)
@@ -139,16 +138,14 @@ internal class FixStackAnalyzer(
val stackSizeWithExtra: Int get() = super.getStackSize() + extraStack.size
fun getStackContent(): List<FixStackValue> {
val savedStack = ArrayList<FixStackValue>()
for (i in 0 until super.getStackSize()) {
savedStack.add(super.getStack(i))
}
fun getStackContent(): List<BasicValue> {
val savedStack = arrayListOf<BasicValue>()
IntRange(0, super.getStackSize() - 1).mapTo(savedStack) { super.getStack(it) }
savedStack.addAll(extraStack)
return savedStack
}
override fun push(value: FixStackValue) {
override fun push(value: BasicValue) {
if (super.getStackSize() < maxStackSize) {
super.push(value)
} else {
@@ -157,27 +154,24 @@ internal class FixStackAnalyzer(
}
}
fun pushAll(values: Collection<FixStackValue>) {
fun pushAll(values: Collection<BasicValue>) {
values.forEach { push(it) }
}
override fun pop(): FixStackValue =
if (extraStack.isNotEmpty()) {
override fun pop(): BasicValue {
return if (extraStack.isNotEmpty()) {
extraStack.pop()
} else {
super.pop()
}
override fun setStack(i: Int, value: FixStackValue) {
if (i < super.getMaxStackSize()) {
super.setStack(i, value)
} else {
extraStack[i - maxStackSize] = value
}
}
override fun merge(frame: Frame<out FixStackValue>, interpreter: Interpreter<FixStackValue>): Boolean {
throw UnsupportedOperationException("Stack normalization should not merge frames")
override fun getStack(i: Int): BasicValue {
return if (i < super.getMaxStackSize()) {
super.getStack(i)
} else {
extraStack[i - maxStackSize]
}
}
}

View File

@@ -1,157 +0,0 @@
/*
* 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.optimization.fixStack
import org.jetbrains.kotlin.codegen.inline.insnOpcodeText
import org.jetbrains.org.objectweb.asm.Handle
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.Interpreter
open class FixStackInterpreter : Interpreter<FixStackValue>(API_VERSION) {
override fun newValue(type: Type?): FixStackValue =
type?.toFixStackValue()
?: FixStackValue.UNINITIALIZED
override fun newOperation(insn: AbstractInsnNode): FixStackValue? =
when (insn.opcode) {
ACONST_NULL ->
FixStackValue.OBJECT
ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5 ->
FixStackValue.INT
LCONST_0, LCONST_1 ->
FixStackValue.LONG
FCONST_0, FCONST_1, FCONST_2 ->
FixStackValue.FLOAT
DCONST_0, DCONST_1 ->
FixStackValue.DOUBLE
BIPUSH, SIPUSH ->
FixStackValue.INT
LDC -> {
when (val cst = (insn as LdcInsnNode).cst) {
is Int ->
FixStackValue.INT
is Float ->
FixStackValue.FLOAT
is Long ->
FixStackValue.LONG
is Double ->
FixStackValue.DOUBLE
is String, is Handle ->
FixStackValue.OBJECT
is Type -> {
val sort = cst.sort
if (sort == Type.OBJECT || sort == Type.ARRAY || sort == Type.METHOD)
FixStackValue.OBJECT
else
throw IllegalArgumentException("Illegal LDC constant $cst")
}
else ->
throw IllegalArgumentException("Illegal LDC constant $cst")
}
}
GETSTATIC ->
newValue(Type.getType((insn as FieldInsnNode).desc))
NEW ->
newValue(Type.getObjectType((insn as TypeInsnNode).desc))
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
override fun copyOperation(insn: AbstractInsnNode, value: FixStackValue?): FixStackValue =
when (insn.opcode) {
ILOAD -> FixStackValue.INT
LLOAD -> FixStackValue.LONG
FLOAD -> FixStackValue.FLOAT
DLOAD -> FixStackValue.DOUBLE
ALOAD -> FixStackValue.OBJECT
else -> value!!
}
override fun binaryOperation(insn: AbstractInsnNode, value1: FixStackValue?, value2: FixStackValue?): FixStackValue? =
when (insn.opcode) {
IALOAD, BALOAD, CALOAD, SALOAD, IADD, ISUB, IMUL, IDIV, IREM, ISHL, ISHR, IUSHR, IAND, IOR, IXOR ->
FixStackValue.INT
FALOAD, FADD, FSUB, FMUL, FDIV, FREM ->
FixStackValue.FLOAT
LALOAD, LADD, LSUB, LMUL, LDIV, LREM, LSHL, LSHR, LUSHR, LAND, LOR, LXOR ->
FixStackValue.LONG
DALOAD, DADD, DSUB, DMUL, DDIV, DREM ->
FixStackValue.DOUBLE
AALOAD ->
FixStackValue.OBJECT
LCMP, FCMPL, FCMPG, DCMPL, DCMPG ->
FixStackValue.INT
IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, PUTFIELD ->
null
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
override fun ternaryOperation(
insn: AbstractInsnNode,
value1: FixStackValue?,
value2: FixStackValue?,
value3: FixStackValue?
): FixStackValue? =
null
override fun naryOperation(insn: AbstractInsnNode, values: List<FixStackValue?>): FixStackValue? =
when (insn.opcode) {
MULTIANEWARRAY ->
newValue(Type.getType((insn as MultiANewArrayInsnNode).desc))
INVOKEDYNAMIC ->
newValue(Type.getReturnType((insn as InvokeDynamicInsnNode).desc))
else ->
newValue(Type.getReturnType((insn as MethodInsnNode).desc))
}
override fun returnOperation(insn: AbstractInsnNode?, value: FixStackValue?, expected: FixStackValue?) {
}
override fun unaryOperation(insn: AbstractInsnNode, value: FixStackValue?): FixStackValue? =
when (insn.opcode) {
INEG, IINC, L2I, F2I, D2I, I2B, I2C, I2S ->
FixStackValue.INT
FNEG, I2F, L2F, D2F ->
FixStackValue.FLOAT
LNEG, I2L, F2L, D2L ->
FixStackValue.LONG
DNEG, I2D, L2D, F2D ->
FixStackValue.DOUBLE
IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, PUTSTATIC ->
null
GETFIELD ->
newValue(Type.getType((insn as FieldInsnNode).desc))
NEWARRAY ->
FixStackValue.OBJECT
ANEWARRAY -> {
FixStackValue.OBJECT
}
ARRAYLENGTH ->
FixStackValue.INT
ATHROW ->
null
CHECKCAST ->
FixStackValue.OBJECT
INSTANCEOF ->
FixStackValue.INT
MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL ->
null
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
override fun merge(v: FixStackValue?, w: FixStackValue?): FixStackValue? =
when {
v == w -> v
v == null -> w
w == null -> v
else -> throw AssertionError("Mismatching value kinds: $v != $w")
}
}

View File

@@ -1,38 +0,0 @@
/*
* 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.optimization.fixStack
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
enum class FixStackValue(
private val _size: Int,
val loadOpcode: Int,
val storeOpcode: Int,
val popOpcode: Int
) : Value {
INT(1, Opcodes.ILOAD, Opcodes.ISTORE, Opcodes.POP),
LONG(2, Opcodes.LLOAD, Opcodes.LSTORE, Opcodes.POP2),
FLOAT(1, Opcodes.FLOAD, Opcodes.FSTORE, Opcodes.POP),
DOUBLE(2, Opcodes.DLOAD, Opcodes.DSTORE, Opcodes.POP2),
OBJECT(1, Opcodes.ALOAD, Opcodes.ASTORE, Opcodes.POP),
UNINITIALIZED(1, -1, -1, -1)
;
override fun getSize(): Int = _size
}
fun Type.toFixStackValue(): FixStackValue? =
when (this.sort) {
Type.VOID -> null
Type.BOOLEAN, Type.BYTE, Type.CHAR, Type.SHORT, Type.INT -> FixStackValue.INT
Type.LONG -> FixStackValue.LONG
Type.FLOAT -> FixStackValue.FLOAT
Type.DOUBLE -> FixStackValue.DOUBLE
Type.OBJECT, Type.ARRAY, Type.METHOD -> FixStackValue.OBJECT
else -> throw AssertionError("Unexpected type: $this")
}

View File

@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.codegen.optimization.fixStack
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import kotlin.math.max
internal class LocalVariablesManager(val context: FixStackContext, val methodNode: MethodNode) {
@@ -38,10 +39,7 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
methodNode.maxLocals = max(methodNode.maxLocals, newValue)
}
fun allocateVariablesForSaveStackMarker(
saveStackMarker: AbstractInsnNode,
savedStackValues: List<FixStackValue>
): SavedStackDescriptor {
fun allocateVariablesForSaveStackMarker(saveStackMarker: AbstractInsnNode, savedStackValues: List<BasicValue>): SavedStackDescriptor {
val numRestoreStackMarkers = context.restoreStackMarkersForSaveMarker[saveStackMarker]!!.size
return allocateNewHandle(numRestoreStackMarkers, saveStackMarker, savedStackValues)
}
@@ -49,10 +47,10 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
private fun allocateNewHandle(
numRestoreStackMarkers: Int,
saveStackMarker: AbstractInsnNode,
savedStackValues: List<FixStackValue>
savedStackValues: List<BasicValue>
): SavedStackDescriptor {
if (savedStackValues.any { it == FixStackValue.UNINITIALIZED }) {
throw AssertionError("Uninitialized value on stack at ${methodNode.instructions.indexOf(saveStackMarker)}: $savedStackValues")
if (savedStackValues.any { it.type == null }) {
throw AssertionError("Uninitialized value on stack at ${methodNode.instructions.indexOf(saveStackMarker)}")
}
val firstUnusedLocalVarIndex = getFirstUnusedLocalVariableIndex()
@@ -80,7 +78,7 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
fun allocateVariablesForBeforeInlineMarker(
beforeInlineMarker: AbstractInsnNode,
savedStackValues: List<FixStackValue>
savedStackValues: List<BasicValue>
): SavedStackDescriptor {
return allocateNewHandle(1, beforeInlineMarker, savedStackValues)
}
@@ -103,7 +101,7 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
}
}
fun createReturnValueVariable(returnValue: FixStackValue): Int {
fun createReturnValueVariable(returnValue: BasicValue): Int {
val returnValueIndex = getFirstUnusedLocalVariableIndex()
updateMaxLocals(returnValueIndex + returnValue.size)
return returnValueIndex

View File

@@ -54,10 +54,10 @@ fun <V : Value> Frame<V>.peekWords(size1: Int, size2: Int): List<V>? {
}
class SavedStackDescriptor(
val savedValues: List<FixStackValue>,
val savedValues: List<BasicValue>,
val firstLocalVarIndex: Int
) {
private val savedValuesSize = savedValues.fold(0) { size, value -> size + value.size }
private val savedValuesSize = savedValues.fold(0, { size, value -> size + value.size })
val firstUnusedLocalVarIndex = firstLocalVarIndex + savedValuesSize
override fun toString(): String =
@@ -88,13 +88,13 @@ fun restoreStackWithReturnValue(
methodNode: MethodNode,
nodeToReplace: AbstractInsnNode,
savedStackDescriptor: SavedStackDescriptor,
returnValue: FixStackValue,
returnValue: BasicValue,
returnValueLocalVarIndex: Int
) {
with(methodNode.instructions) {
insertBefore(nodeToReplace, VarInsnNode(returnValue.storeOpcode, returnValueLocalVarIndex))
insertBefore(nodeToReplace, VarInsnNode(returnValue.type.getOpcode(Opcodes.ISTORE), returnValueLocalVarIndex))
generateLoadInstructions(methodNode, nodeToReplace, savedStackDescriptor)
insertBefore(nodeToReplace, VarInsnNode(returnValue.loadOpcode, returnValueLocalVarIndex))
insertBefore(nodeToReplace, VarInsnNode(returnValue.type.getOpcode(Opcodes.ILOAD), returnValueLocalVarIndex))
remove(nodeToReplace)
}
}
@@ -102,7 +102,10 @@ fun restoreStackWithReturnValue(
fun generateLoadInstructions(methodNode: MethodNode, location: AbstractInsnNode, savedStackDescriptor: SavedStackDescriptor) {
var localVarIndex = savedStackDescriptor.firstLocalVarIndex
for (value in savedStackDescriptor.savedValues) {
methodNode.instructions.insertBefore(location, VarInsnNode(value.loadOpcode, localVarIndex))
methodNode.instructions.insertBefore(
location,
VarInsnNode(value.type.getOpcode(Opcodes.ILOAD), localVarIndex)
)
localVarIndex += value.size
}
}
@@ -111,7 +114,10 @@ fun generateStoreInstructions(methodNode: MethodNode, location: AbstractInsnNode
var localVarIndex = savedStackDescriptor.firstUnusedLocalVarIndex
for (value in savedStackDescriptor.savedValues.asReversed()) {
localVarIndex -= value.size
methodNode.instructions.insertBefore(location, VarInsnNode(value.storeOpcode, localVarIndex))
methodNode.instructions.insertBefore(
location,
VarInsnNode(value.type.getOpcode(Opcodes.ISTORE), localVarIndex)
)
}
}
@@ -140,10 +146,10 @@ fun replaceAlwaysTrueIfeqWithGoto(methodNode: MethodNode, node: AbstractInsnNode
}
}
fun replaceMarkerWithPops(methodNode: MethodNode, node: AbstractInsnNode, expectedStackSize: Int, stackContent: List<FixStackValue>) {
fun replaceMarkerWithPops(methodNode: MethodNode, node: AbstractInsnNode, expectedStackSize: Int, stackContent: List<BasicValue>) {
with(methodNode.instructions) {
for (stackValue in stackContent.subList(expectedStackSize, stackContent.size)) {
insert(node, InsnNode(stackValue.popOpcode))
insert(node, getPopInstruction(stackValue))
}
remove(node)
}

View File

@@ -35,8 +35,6 @@ public final class JvmSerializationBindings {
SerializationMappingSlice.create();
public static final SerializationMappingSlice<PropertyDescriptor, Method> SYNTHETIC_METHOD_FOR_PROPERTY =
SerializationMappingSlice.create();
public static final SerializationMappingSlice<PropertyDescriptor, Method> DELEGATE_METHOD_FOR_PROPERTY =
SerializationMappingSlice.create();
public static final class SerializationMappingSlice<K, V> extends BasicWritableSlice<K, V> {
public SerializationMappingSlice() {

View File

@@ -255,15 +255,12 @@ class JvmSerializerExtension @JvmOverloads constructor(
val field = getBinding(FIELD_FOR_PROPERTY, descriptor)
val syntheticMethod = getBinding(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor)
val delegateMethod = getBinding(DELEGATE_METHOD_FOR_PROPERTY, descriptor)
assert(descriptor.isDelegated || delegateMethod == null) { "non-delegated property $descriptor has delegate method" }
val signature = signatureSerializer.propertySignature(
descriptor,
field?.second,
field?.first?.descriptor,
if (syntheticMethod != null) signatureSerializer.methodSignature(null, syntheticMethod) else null,
if (delegateMethod != null) signatureSerializer.methodSignature(null, delegateMethod) else null,
if (getterMethod != null) signatureSerializer.methodSignature(null, getterMethod) else null,
if (setterMethod != null) signatureSerializer.methodSignature(null, setterMethod) else null
)
@@ -362,7 +359,6 @@ class JvmSerializerExtension @JvmOverloads constructor(
fieldName: String?,
fieldDesc: String?,
syntheticMethod: JvmProtoBuf.JvmMethodSignature?,
delegateMethod: JvmProtoBuf.JvmMethodSignature?,
getter: JvmProtoBuf.JvmMethodSignature?,
setter: JvmProtoBuf.JvmMethodSignature?
): JvmProtoBuf.JvmPropertySignature? {
@@ -377,10 +373,6 @@ class JvmSerializerExtension @JvmOverloads constructor(
signature.syntheticMethod = syntheticMethod
}
if (delegateMethod != null) {
signature.delegateMethod = delegateMethod
}
if (getter != null) {
signature.getter = getter
}

View File

@@ -407,7 +407,6 @@ class GenerationState private constructor(
this[KOTLIN_1_4] = JvmMetadataVersion(1, 4, 3)
this[KOTLIN_1_5] = JvmMetadataVersion.INSTANCE
this[KOTLIN_1_6] = JvmMetadataVersion(1, 6, 0)
this[KOTLIN_1_7] = JvmMetadataVersion(1, 7, 0)
check(size == LanguageVersion.values().size) {
"Please add mappings from the missing LanguageVersion instances to the corresponding JvmMetadataVersion " +

View File

@@ -1,5 +1,6 @@
<idea-plugin>
<id>org.jetbrains.kotlin</id>
<version>1.2</version>
<extensionPoints>
<extensionPoint qualifiedName="org.jetbrains.kotlin.analyzeCompleteHandlerExtension"

View File

@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.cli.common.arguments
import com.intellij.util.xmlb.annotations.Transient
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.*
import java.util.*
@@ -83,15 +82,6 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
@Argument(value = "-P", valueDescription = PLUGIN_OPTION_FORMAT, description = "Pass an option to a plugin")
var pluginOptions: Array<String>? by FreezableVar(null)
@Argument(
value = "-opt-in",
// Uncomment after deletion of optInDeprecated
// deprecatedName = "-Xopt-in",
valueDescription = "<fq.name>",
description = "Enable usages of API that requires opt-in with an opt-in requirement marker with the given fully qualified name"
)
var optIn: Array<String>? by FreezableVar(null)
// Advanced options
@Argument(value = "-Xno-inline", description = "Disable method inlining")
@@ -167,6 +157,13 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
)
var readDeserializedContracts: Boolean by FreezableVar(false)
@Argument(
value = "-Xexperimental",
valueDescription = "<fq.name>",
description = "Enable and propagate usages of experimental API for marker annotation with the given fully qualified name"
)
var experimental: Array<String>? by FreezableVar(null)
@Argument(
value = "-Xuse-experimental",
valueDescription = "<fq.name>",
@@ -174,13 +171,12 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
)
var useExperimental: Array<String>? by FreezableVar(null)
// NB: we have to keep this flag for some time due to bootstrapping problems
@Argument(
value = "-Xopt-in",
valueDescription = "<fq.name>",
description = "Enable usages of API that requires opt-in with an opt-in requirement marker with the given fully qualified name"
)
var optInDeprecated: Array<String>? by FreezableVar(null)
var optIn: Array<String>? by FreezableVar(null)
@Argument(
value = "-Xproper-ieee754-comparisons",
@@ -369,38 +365,17 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
)
var extendedCompilerChecks: Boolean by FreezableVar(false)
@GradleOption(DefaultValues.BooleanFalseDefault::class)
@Argument(
value = "-Xbuiltins-from-sources",
description = "Compile builtIns from sources"
)
var builtInsFromSources: Boolean by FreezableVar(false)
@Argument(
value = "-Xunrestricted-builder-inference",
description = "Eliminate builder inference restrictions like allowance of returning type variables of a builder inference call"
)
var unrestrictedBuilderInference: Boolean by FreezableVar(false)
open fun configureAnalysisFlags(collector: MessageCollector, languageVersion: LanguageVersion): MutableMap<AnalysisFlag<*>, Any> {
return HashMap<AnalysisFlag<*>, Any>().apply {
put(AnalysisFlags.skipMetadataVersionCheck, skipMetadataVersionCheck)
put(AnalysisFlags.skipPrereleaseCheck, skipPrereleaseCheck || skipMetadataVersionCheck)
put(AnalysisFlags.multiPlatformDoNotCheckActual, noCheckActual)
val useExperimentalFqNames = useExperimental?.toList().orEmpty()
if (useExperimentalFqNames.isNotEmpty()) {
collector.report(
WARNING, "'-Xuse-experimental' is deprecated and will be removed in a future release, please use -opt-in instead"
)
val experimentalFqNames = experimental?.toList().orEmpty()
if (experimentalFqNames.isNotEmpty()) {
put(AnalysisFlags.experimental, experimentalFqNames)
collector.report(CompilerMessageSeverity.WARNING, "'-Xexperimental' is deprecated and will be removed in a future release")
}
val optInDeprecatedFqNames = optInDeprecated?.toList().orEmpty()
if (optInDeprecatedFqNames.isNotEmpty()) {
// TODO: uncomment this after -opt-in bootstrapping and Gradle script fixing
// collector.report(
// WARNING, "'-Xopt-in' is deprecated and will be removed in a future release, please use -opt-in instead"
// )
}
put(AnalysisFlags.useExperimental, useExperimentalFqNames + optInDeprecatedFqNames + optIn?.toList().orEmpty())
put(AnalysisFlags.useExperimental, useExperimental?.toList().orEmpty() + optIn?.toList().orEmpty())
put(AnalysisFlags.expectActualLinker, expectActualLinker)
put(AnalysisFlags.explicitApiVersion, apiVersion != null)
put(AnalysisFlags.allowResultReturnType, allowResultReturnType)
@@ -410,7 +385,6 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
)
put(AnalysisFlags.extendedCompilerChecks, extendedCompilerChecks)
put(AnalysisFlags.allowKotlinPackage, allowKotlinPackage)
put(AnalysisFlags.builtInsFromSources, builtInsFromSources)
}
}
@@ -420,10 +394,6 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
put(LanguageFeature.MultiPlatformProjects, LanguageFeature.State.ENABLED)
}
if (unrestrictedBuilderInference) {
put(LanguageFeature.UnrestrictedBuilderInference, LanguageFeature.State.ENABLED)
}
if (newInference) {
put(LanguageFeature.NewInference, LanguageFeature.State.ENABLED)
put(LanguageFeature.SamConversionPerArgument, LanguageFeature.State.ENABLED)

View File

@@ -499,12 +499,6 @@ default: `indy-with-constants` for JVM target 9 or greater, `inline` otherwise""
)
var typeEnhancementImprovementsInStrictMode: Boolean by FreezableVar(false)
@Argument(
value = "-Xserialize-ir",
description = "Save IR to metadata (EXPERIMENTAL)"
)
var serializeIr: Boolean by FreezableVar(false)
override fun configureAnalysisFlags(collector: MessageCollector, languageVersion: LanguageVersion): MutableMap<AnalysisFlag<*>, Any> {
val result = super.configureAnalysisFlags(collector, languageVersion)
result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics

View File

@@ -107,7 +107,7 @@ private fun <A : CommonToolArguments> parsePreprocessedCommandLineArguments(args
return arg.startsWith(argument.value + "=")
}
return argument.value == arg || arg.startsWith(argument.value + "=")
return argument.value == arg
}
val freeArgs = ArrayList<String>()
@@ -160,10 +160,10 @@ private fun <A : CommonToolArguments> parsePreprocessedCommandLineArguments(args
val (property, argument) = argumentField
val value: Any = when {
argumentField.property.returnType.classifier == Boolean::class -> true
arg.startsWith(argument.value + "=") -> {
argument.isAdvanced && arg.startsWith(argument.value + "=") -> {
arg.substring(argument.value.length + 1)
}
arg.startsWith(argument.deprecatedName + "=") -> {
argument.isAdvanced && arg.startsWith(argument.deprecatedName + "=") -> {
arg.substring(argument.deprecatedName.length + 1)
}
i == args.size -> {

View File

@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
import org.jetbrains.kotlin.cli.common.extensions.ScriptEvaluationExtension
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageUtil
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
@@ -47,6 +48,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.serialization.js.ModuleKind
import org.jetbrains.kotlin.util.Logger
import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.utils.PathUtil
import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull
@@ -179,6 +181,17 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
// TODO: Handle non-empty main call arguments
val mainCallArguments = if (K2JsArgumentConstants.NO_CALL == arguments.main) null else emptyList<String>()
val resolvedLibraries = jsResolveLibraries(
libraries,
configuration[JSConfigurationKeys.REPOSITORIES] ?: emptyList(),
messageCollectorLogger(configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY] ?: error("Could not find message collector"))
)
val friendAbsolutePaths = friendLibraries.map { File(it).absolutePath }
val friendDependencies = resolvedLibraries.getFullList().filter {
it.libraryFile.absolutePath in friendAbsolutePaths
}
if (arguments.irProduceKlibDir || arguments.irProduceKlibFile) {
if (arguments.irProduceKlibFile) {
require(outputFile.extension == KLIB_FILE_EXTENSION) { "Please set up .klib file as output" }
@@ -189,8 +202,8 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
files = sourcesFiles,
analyzer = AnalyzerWithCompilerReport(config.configuration),
configuration = config.configuration,
dependencies = libraries,
friendDependencies = friendLibraries,
allDependencies = resolvedLibraries,
friendDependencies = friendDependencies,
irFactory = PersistentIrFactory(), // TODO IrFactoryImpl?
outputKlibPath = outputFile.path,
nopack = arguments.irProduceKlibDir,
@@ -207,10 +220,9 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
if (sourcesFiles.isNotEmpty()) {
messageCollector.report(ERROR, "Source files are not supported when -Xinclude is present")
}
val includesPath = File(includes).canonicalPath
val mainLibPath = libraries.find { File(it).canonicalPath == includesPath }
?: error("No library with name $includes ($includesPath) found")
MainModule.Klib(mainLibPath)
val allLibraries = resolvedLibraries.getFullList()
val mainLib = allLibraries.find { it.libraryFile.absolutePath == File(includes).absolutePath }!!
MainModule.Klib(mainLib)
} else {
MainModule.SourceFiles(sourcesFiles)
}
@@ -223,8 +235,8 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
config.configuration,
PhaseConfig(wasmPhases),
IrFactoryImpl,
dependencies = libraries,
friendDependencies = friendLibraries,
allDependencies = resolvedLibraries,
friendDependencies = friendDependencies,
exportedDeclarations = setOf(FqName("main"))
)
val outputWasmFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "wasm")!!
@@ -250,8 +262,8 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
config.configuration,
phaseConfig,
if (arguments.irDceDriven) PersistentIrFactory() else IrFactoryImpl,
dependencies = libraries,
friendDependencies = friendLibraries,
allDependencies = resolvedLibraries,
friendDependencies = friendDependencies,
mainArguments = mainCallArguments,
generateFullJs = !arguments.irDce,
generateDceJs = arguments.irDce,
@@ -464,6 +476,17 @@ fun RuntimeDiagnostic.Companion.resolve(
}
}
fun messageCollectorLogger(collector: MessageCollector) = object : Logger {
override fun warning(message: String) = collector.report(STRONG_WARNING, message)
override fun error(message: String) = collector.report(ERROR, message)
override fun log(message: String) = collector.report(LOGGING, message)
override fun fatal(message: String): Nothing {
collector.report(ERROR, message)
(collector as? GroupingMessageCollector)?.flush()
kotlin.error(message)
}
}
fun loadPluginsForTests(configuration: CompilerConfiguration): ExitCode {
var pluginClasspaths: Iterable<String> = emptyList()
val kotlinPaths = PathUtil.kotlinPathsForCompiler

View File

@@ -17,14 +17,7 @@ interface AsyncProfilerReflected {
}
object AsyncProfilerHelper {
private var instance: AsyncProfilerReflected? = null
fun getInstance(libPath: String?): AsyncProfilerReflected {
// JVM doesn't support loading a native library multiple times even in different class loaders, so we don't attempt to load
// async-profiler again after the first use, which allows to profile the same compiler process multiple times,
// for example in the compiler daemon scenario.
instance?.let { return it }
val profilerClass = loadAsyncProfilerClass(libPath)
val getInstanceHandle =
MethodHandles.lookup().findStatic(profilerClass, "getInstance", MethodType.methodType(profilerClass, String::class.java))
@@ -56,7 +49,7 @@ object AsyncProfilerHelper {
override val version: String
get() = boundGetVersion.invokeWithArguments() as String
}.also { this.instance = it }
}
}
private fun loadAsyncProfilerClass(libPath: String?): Class<*> {

View File

@@ -303,7 +303,6 @@ object JvmRuntimeVersionsConsistencyChecker {
}
FileKind.OldRuntime -> jars.add(KotlinLibraryFile(jarFile, ApiVersion.KOTLIN_1_0.version))
FileKind.LibraryWithBundledRuntime -> otherLibrariesWithBundledRuntime.add(jarFile)
FileKind.Irrelevant -> {}
}
}

View File

@@ -5,15 +5,12 @@
package org.jetbrains.kotlin.cli.jvm.compiler
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.openapi.vfs.VirtualFileSystem
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.ProjectScope
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
@@ -21,7 +18,6 @@ import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensionsImpl
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.backend.jvm.jvmPhases
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager
import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage
import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
@@ -31,38 +27,29 @@ import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.CodegenFactory
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.backend.Fir2IrResult
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.java.FirJavaElementFinder
import org.jetbrains.kotlin.fir.session.FirSessionFactory
import org.jetbrains.kotlin.fir.session.FirSessionFactory.createSessionWithDependencies
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
import java.io.File
import kotlin.collections.set
object FirKotlinToJvmBytecodeCompiler {
fun compileModulesUsingFrontendIR(
@@ -90,24 +77,145 @@ object FirKotlinToJvmBytecodeCompiler {
val outputs = newLinkedHashMapWithExpectedSize<Module, GenerationState>(chunk.size)
val targetIds = environment.configuration.get(JVMConfigurationKeys.MODULES)?.map(::TargetId)
val incrementalComponents = environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS)
val isMultiModuleChunk = chunk.size > 1
for (module in chunk) {
performanceManager?.notifyAnalysisStarted()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val ktFiles = module.getSourceFiles(environment, localFileSystem, chunk.size > 1, buildFile)
if (!checkKotlinPackageUsage(environment, ktFiles)) return false
val syntaxErrors = ktFiles.fold(false) { errorsFound, ktFile ->
AnalyzerWithCompilerReport.reportSyntaxErrors(ktFile, environment.messageCollector).isHasErrors or errorsFound
}
val moduleConfiguration = projectConfiguration.applyModuleProperties(module, buildFile)
val context = CompilationContext(
module,
val sourceScope = GlobalSearchScope.filesWithoutLibrariesScope(project, ktFiles.map { it.virtualFile })
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project))
var librariesScope = ProjectScope.getLibrariesScope(project)
val providerAndScopeForIncrementalCompilation = run {
if (targetIds == null || incrementalComponents == null) return@run null
val fileSystem = environment.projectEnvironment.environment.localFileSystem
val directoryWithIncrementalPartsFromPreviousCompilation =
moduleConfiguration[JVMConfigurationKeys.OUTPUT_DIRECTORY]
?: return@run null
val previouslyCompiledFiles = directoryWithIncrementalPartsFromPreviousCompilation.walk()
.filter { it.extension == "class" }
.mapNotNull { fileSystem.findFileByIoFile(it) }
.toList()
.takeIf { it.isNotEmpty() }
?: return@run null
val packagePartProvider = IncrementalPackagePartProvider(
environment.createPackagePartProvider(sourceScope),
targetIds.map(incrementalComponents::getIncrementalCache)
)
val incrementalCompilationScope = GlobalSearchScope.filesWithoutLibrariesScope(
project,
previouslyCompiledFiles
)
librariesScope = librariesScope.intersectWith(GlobalSearchScope.notScope(incrementalCompilationScope))
FirSessionFactory.ProviderAndScopeForIncrementalCompilation(packagePartProvider, incrementalCompilationScope)
}
val languageVersionSettings = moduleConfiguration.languageVersionSettings
val session = createSessionWithDependencies(
Name.identifier(module.getModuleName()),
JvmPlatforms.unspecifiedJvmPlatform,
JvmPlatformAnalyzerServices,
externalSessionProvider = null,
project,
environment,
moduleConfiguration,
localFileSystem,
isMultiModuleChunk,
buildFile,
performanceManager,
targetIds,
incrementalComponents,
extendedAnalysisMode
languageVersionSettings,
sourceScope,
librariesScope,
lookupTracker = environment.configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER),
providerAndScopeForIncrementalCompilation,
getPackagePartProvider = { environment.createPackagePartProvider(it) },
dependenciesConfigurator = {
dependencies(moduleConfiguration.jvmClasspathRoots.map { it.toPath() })
dependencies(moduleConfiguration.jvmModularRoots.map { it.toPath() })
friendDependencies(moduleConfiguration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList())
},
sessionConfigurator = {
if (extendedAnalysisMode) {
registerExtendedCommonCheckers()
}
}
)
val generationState = context.compileModule() ?: return false
val firAnalyzerFacade = FirAnalyzerFacade(session, languageVersionSettings, ktFiles)
firAnalyzerFacade.runResolution()
val firDiagnostics = firAnalyzerFacade.runCheckers().values.flatten()
val hasErrors = FirDiagnosticsCompilerResultsReporter.reportDiagnostics(firDiagnostics, environment.messageCollector)
performanceManager?.notifyAnalysisFinished()
if (syntaxErrors || hasErrors) {
return false
}
performanceManager?.notifyGenerationStarted()
performanceManager?.notifyIRTranslationStarted()
val extensions = JvmGeneratorExtensionsImpl()
val (moduleFragment, symbolTable, components) = firAnalyzerFacade.convertToIr(extensions)
performanceManager?.notifyIRTranslationFinished()
val dummyBindingContext = NoScopeRecordCliBindingTrace().bindingContext
val codegenFactory = JvmIrCodegenFactory(moduleConfiguration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases))
// Create and initialize the module and its dependencies
val container = TopDownAnalyzerFacadeForJVM.createContainer(
project, ktFiles, NoScopeRecordCliBindingTrace(), environment.configuration, environment::createPackagePartProvider,
::FileBasedDeclarationProviderFactory, CompilerEnvironment,
TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles), emptyList()
)
val generationState = GenerationState.Builder(
environment.project, ClassBuilderFactories.BINARIES,
container.get(), dummyBindingContext, ktFiles,
moduleConfiguration
).codegenFactory(
codegenFactory
).withModule(
module
).onIndependentPartCompilationEnd(
createOutputFilesFlushingCallbackIfPossible(moduleConfiguration)
).isIrBackend(
true
).jvmBackendClassResolver(
FirJvmBackendClassResolver(components)
).build()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
performanceManager?.notifyIRLoweringStarted()
generationState.beforeCompile()
codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, extensions, FirJvmBackendExtension(session, components)
) {
performanceManager?.notifyIRLoweringFinished()
performanceManager?.notifyIRGenerationStarted()
}
CodegenFactory.doCheckCancelled(generationState)
generationState.factory.done()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
AnalyzerWithCompilerReport.reportDiagnostics(
FilteredJvmDiagnostics(
generationState.collectedExtraJvmDiagnostics,
dummyBindingContext.diagnostics
),
environment.messageCollector
)
performanceManager?.notifyIRGenerationFinished()
performanceManager?.notifyGenerationFinished()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
outputs[module] = generationState
Disposer.dispose(environment.project)
@@ -120,229 +228,4 @@ object FirKotlinToJvmBytecodeCompiler {
return writeOutputs(environment, projectConfiguration, chunk, outputs, mainClassFqName)
}
private fun CompilationContext.compileModule(): GenerationState? {
performanceManager?.notifyAnalysisStarted()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val ktFiles = module.getSourceFiles(environment, localFileSystem, isMultiModuleChunk, buildFile)
if (!checkKotlinPackageUsage(environment, ktFiles)) return null
val firAnalyzerFacade = runFrontend(ktFiles).also {
performanceManager?.notifyAnalysisFinished()
} ?: return null
performanceManager?.notifyGenerationStarted()
performanceManager?.notifyIRTranslationStarted()
val extensions = JvmGeneratorExtensionsImpl(moduleConfiguration)
val fir2IrResult = firAnalyzerFacade.convertToIr(extensions)
val session = firAnalyzerFacade.session
performanceManager?.notifyIRTranslationFinished()
val generationState = runBackend(
ktFiles,
fir2IrResult,
extensions,
session
)
performanceManager?.notifyIRGenerationFinished()
performanceManager?.notifyGenerationFinished()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
return generationState
}
private fun CompilationContext.runFrontend(ktFiles: List<KtFile>): FirAnalyzerFacade? {
@Suppress("NAME_SHADOWING")
var ktFiles = ktFiles
val syntaxErrors = ktFiles.fold(false) { errorsFound, ktFile ->
AnalyzerWithCompilerReport.reportSyntaxErrors(ktFile, environment.messageCollector).isHasErrors or errorsFound
}
var sourceScope = GlobalSearchScope.filesWithoutLibrariesScope(project, ktFiles.map { it.virtualFile })
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project))
var librariesScope = ProjectScope.getLibrariesScope(project)
val providerAndScopeForIncrementalCompilation = createComponentsForIncrementalCompilation(sourceScope)
providerAndScopeForIncrementalCompilation?.scope?.let {
librariesScope = librariesScope.intersectWith(GlobalSearchScope.notScope(it))
}
val languageVersionSettings = moduleConfiguration.languageVersionSettings
val commonKtFiles = ktFiles.filter { it.isCommonSource == true }
val sessionProvider = FirProjectSessionProvider()
fun createSession(
name: String,
platform: TargetPlatform,
analyzerServices: PlatformDependentAnalyzerServices,
sourceScope: GlobalSearchScope,
dependenciesConfigurator: DependencyListForCliModule.Builder.() -> Unit = {}
): FirSession {
return createSessionWithDependencies(
Name.identifier(name),
platform,
analyzerServices,
externalSessionProvider = sessionProvider,
project,
languageVersionSettings,
sourceScope,
librariesScope,
lookupTracker = environment.configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER),
providerAndScopeForIncrementalCompilation,
getPackagePartProvider = { environment.createPackagePartProvider(it) },
dependenciesConfigurator = {
dependencies(moduleConfiguration.jvmClasspathRoots.map { it.toPath() })
dependencies(moduleConfiguration.jvmModularRoots.map { it.toPath() })
friendDependencies(moduleConfiguration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList())
dependenciesConfigurator()
},
sessionConfigurator = {
if (extendedAnalysisMode) {
registerExtendedCommonCheckers()
}
}
)
}
val commonSession = runIf(
languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) && commonKtFiles.isNotEmpty()
) {
val commonSourcesScope = GlobalSearchScope.filesWithoutLibrariesScope(project, commonKtFiles.map { it.virtualFile })
sourceScope = sourceScope.intersectWith(GlobalSearchScope.notScope(commonSourcesScope))
ktFiles = ktFiles.filterNot { it.isCommonSource == true }
createSession(
"${module.getModuleName()}-common",
CommonPlatforms.defaultCommonPlatform,
CommonPlatformAnalyzerServices,
commonSourcesScope
)
}
val session = createSession(
module.getModuleName(),
JvmPlatforms.unspecifiedJvmPlatform,
JvmPlatformAnalyzerServices,
sourceScope
) {
if (commonSession != null) {
sourceDependsOnDependencies(listOf(commonSession.moduleData))
}
}
val commonAnalyzerFacade = commonSession?.let { FirAnalyzerFacade(it, languageVersionSettings, commonKtFiles) }
val firAnalyzerFacade = FirAnalyzerFacade(session, languageVersionSettings, ktFiles)
commonAnalyzerFacade?.runResolution()
val allFirDiagnostics = mutableListOf<FirDiagnostic>()
commonAnalyzerFacade?.runCheckers()?.values?.flattenTo(allFirDiagnostics)
firAnalyzerFacade.runResolution()
firAnalyzerFacade.runCheckers().values.flattenTo(allFirDiagnostics)
val hasErrors = FirDiagnosticsCompilerResultsReporter.reportDiagnostics(allFirDiagnostics, environment.messageCollector)
return firAnalyzerFacade.takeUnless { syntaxErrors || hasErrors }
}
private fun CompilationContext.createComponentsForIncrementalCompilation(
sourceScope: GlobalSearchScope
): FirSessionFactory.ProviderAndScopeForIncrementalCompilation? {
if (targetIds == null || incrementalComponents == null) return null
val fileSystem = environment.projectEnvironment.environment.localFileSystem
val directoryWithIncrementalPartsFromPreviousCompilation =
moduleConfiguration[JVMConfigurationKeys.OUTPUT_DIRECTORY]
?: return null
val previouslyCompiledFiles = directoryWithIncrementalPartsFromPreviousCompilation.walk()
.filter { it.extension == "class" }
.mapNotNull { fileSystem.findFileByIoFile(it) }
.toList()
.takeIf { it.isNotEmpty() }
?: return null
val packagePartProvider = IncrementalPackagePartProvider(
environment.createPackagePartProvider(sourceScope),
targetIds.map(incrementalComponents::getIncrementalCache)
)
val incrementalCompilationScope = GlobalSearchScope.filesWithoutLibrariesScope(
project,
previouslyCompiledFiles
)
return FirSessionFactory.ProviderAndScopeForIncrementalCompilation(packagePartProvider, incrementalCompilationScope)
}
private fun CompilationContext.runBackend(
ktFiles: List<KtFile>,
fir2IrResult: Fir2IrResult,
extensions: JvmGeneratorExtensionsImpl,
session: FirSession
): GenerationState {
val (moduleFragment, symbolTable, components) = fir2IrResult
val dummyBindingContext = NoScopeRecordCliBindingTrace().bindingContext
val codegenFactory = JvmIrCodegenFactory(
moduleConfiguration,
moduleConfiguration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases),
jvmGeneratorExtensions = extensions
)
val generationState = GenerationState.Builder(
environment.project, ClassBuilderFactories.BINARIES,
moduleFragment.descriptor, dummyBindingContext, ktFiles,
moduleConfiguration
).codegenFactory(
codegenFactory
).withModule(
module
).onIndependentPartCompilationEnd(
createOutputFilesFlushingCallbackIfPossible(moduleConfiguration)
).isIrBackend(
true
).jvmBackendClassResolver(
FirJvmBackendClassResolver(components)
).build()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
performanceManager?.notifyIRLoweringStarted()
generationState.beforeCompile()
codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, extensions, FirJvmBackendExtension(session, components)
) {
performanceManager?.notifyIRLoweringFinished()
performanceManager?.notifyIRGenerationStarted()
}
CodegenFactory.doCheckCancelled(generationState)
generationState.factory.done()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
AnalyzerWithCompilerReport.reportDiagnostics(
FilteredJvmDiagnostics(
generationState.collectedExtraJvmDiagnostics,
dummyBindingContext.diagnostics
),
environment.messageCollector
)
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
return generationState
}
private class CompilationContext(
val module: Module,
val project: Project,
val environment: KotlinCoreEnvironment,
val moduleConfiguration: CompilerConfiguration,
val localFileSystem: VirtualFileSystem,
val isMultiModuleChunk: Boolean,
val buildFile: File?,
val performanceManager: CommonCompilerPerformanceManager?,
val targetIds: List<TargetId>?,
val incrementalComponents: IncrementalCompilationComponents?,
val extendedAnalysisMode: Boolean
)
}

View File

@@ -306,7 +306,7 @@ object KotlinToJVMBytecodeCompiler {
)
.codegenFactory(
if (configuration.getBoolean(JVMConfigurationKeys.IR)) JvmIrCodegenFactory(
configuration, configuration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases)
configuration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases)
) else DefaultCodegenFactory
)
.withModule(module)

View File

@@ -252,8 +252,6 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(JVMConfigurationKeys.NO_RESET_JAR_TIMESTAMPS, arguments.noResetJarTimestamps)
put(JVMConfigurationKeys.NO_UNIFIED_NULL_CHECKS, arguments.noUnifiedNullChecks)
put(JVMConfigurationKeys.SERIALIZE_IR, arguments.serializeIr)
if (!JVMConstructorCallNormalizationMode.isSupportedValue(arguments.constructorCallNormalizationMode)) {
messageCollector.report(
ERROR,

View File

@@ -47,32 +47,14 @@ object KotlinCompilerRunnerUtils {
isDebugEnabled: Boolean,
daemonOptions: DaemonOptions = configureDaemonOptions(),
additionalJvmParams: Array<String> = arrayOf()
): CompileServiceSession? = newDaemonConnection(
compilerId,
clientAliveFlagFile,
sessionAliveFlagFile,
messageCollector,
isDebugEnabled,
daemonOptions,
configureDaemonJVMOptions(
): CompileServiceSession? {
val daemonJVMOptions = configureDaemonJVMOptions(
*additionalJvmParams,
inheritMemoryLimits = true,
inheritOtherJvmOptions = false,
inheritAdditionalProperties = true
)
)
@Synchronized
@JvmStatic
fun newDaemonConnection(
compilerId: CompilerId,
clientAliveFlagFile: File,
sessionAliveFlagFile: File,
messageCollector: MessageCollector,
isDebugEnabled: Boolean,
daemonOptions: DaemonOptions = configureDaemonOptions(),
daemonJVMOptions: DaemonJVMOptions
): CompileServiceSession? {
val daemonReportMessages = ArrayList<DaemonReportMessage>()
val daemonReportingTargets = DaemonReportingTargets(messages = daemonReportMessages)

View File

@@ -152,7 +152,4 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> NO_REFLECT =
CompilerConfigurationKey.create("Don't automatically include kotlin-reflect.jar into the output if the output is a jar");
public static final CompilerConfigurationKey<Boolean> SERIALIZE_IR =
CompilerConfigurationKey.create("serialize IR to class metadata");
}

View File

@@ -18,6 +18,9 @@ object AnalysisFlags {
@JvmStatic
val expectActualLinker by AnalysisFlag.Delegates.Boolean
@JvmStatic
val experimental by AnalysisFlag.Delegates.ListOfStrings
@JvmStatic
val useExperimental by AnalysisFlag.Delegates.ListOfStrings
@@ -53,7 +56,4 @@ object AnalysisFlags {
@JvmStatic
val allowKotlinPackage by AnalysisFlag.Delegates.Boolean
@JvmStatic
val builtInsFromSources by AnalysisFlag.Delegates.Boolean
}

View File

@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.daemon.common
import org.jetbrains.kotlin.incremental.ClasspathChanges
import org.jetbrains.kotlin.incremental.IncrementalModuleInfo
import java.io.File
import java.io.Serializable
@@ -53,7 +52,6 @@ class IncrementalCompilationOptions(
val areFileChangesKnown: Boolean,
val modifiedFiles: List<File>?,
val deletedFiles: List<File>?,
val classpathChanges: ClasspathChanges,
val workingDir: File,
compilerMode: CompilerMode,
targetPlatform: CompileService.TargetPlatform,
@@ -89,7 +87,6 @@ class IncrementalCompilationOptions(
"areFileChangesKnown=$areFileChangesKnown, " +
"modifiedFiles=$modifiedFiles, " +
"deletedFiles=$deletedFiles, " +
"classpathChanges=$classpathChanges, " +
"workingDir=$workingDir, " +
"multiModuleICSettings=$multiModuleICSettings, " +
"usePreciseJavaTracking=$usePreciseJavaTracking" +

View File

@@ -601,8 +601,7 @@ abstract class CompileServiceImplBase(
outputFiles = incrementalCompilationOptions.outputFiles,
usePreciseJavaTracking = incrementalCompilationOptions.usePreciseJavaTracking,
modulesApiHistory = modulesApiHistory,
kotlinSourceFilesExtensions = allKotlinExtensions,
classpathChanges = incrementalCompilationOptions.classpathChanges
kotlinSourceFilesExtensions = allKotlinExtensions
)
return try {
compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles, projectRoot)

View File

@@ -7,14 +7,12 @@ package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
@OptIn(SymbolInternals::class)
abstract class AbstractFirLoadBinariesTest : AbstractFirResolveWithSessionTestCase() {
/**
* Since fir symbol providers can't get all names in package (only fir provider can do it),

View File

@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.fir.createSessionForTests
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -40,7 +39,6 @@ import java.io.File
import java.io.IOException
import kotlin.reflect.jvm.javaField
@OptIn(SymbolInternals::class)
abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() {
private lateinit var javaFilesDir: File

View File

@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.java
import org.jetbrains.kotlin.fir.FirRenderer
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
@@ -16,10 +16,8 @@ import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@OptIn(SymbolInternals::class)
fun renderJavaClass(renderer: FirRenderer, javaClass: FirJavaClass, session: FirSession) {
val memberScope = javaClass.unsubstitutedScope(session, ScopeSession(), withForcedTypeCalculator = true)
@@ -44,7 +42,7 @@ fun renderJavaClass(renderer: FirRenderer, javaClass: FirJavaClass, session: Fir
if (declaration in renderedDeclarations) continue
val scopeToUse =
if (declaration is FirCallableDeclaration && declaration.status.isStatic)
if (declaration is FirCallableMemberDeclaration && declaration.status.isStatic)
staticScope
else
memberScope

View File

@@ -1,4 +1,4 @@
@R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.NEVER|()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) public final annotation class MyNullable : R|kotlin/Annotation| {
@R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.NEVER|()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) public abstract annotation class MyNullable : R|kotlin/Annotation| {
public constructor(): R|MyNullable|
}

View File

@@ -10,7 +10,7 @@
public constructor(): R|A|
}
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public final annotation class FieldsAreNullable : R|kotlin/Annotation| {
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class FieldsAreNullable : R|kotlin/Annotation| {
public constructor(): R|FieldsAreNullable|
}

View File

@@ -6,19 +6,19 @@
public constructor(): R|A|
}
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public final annotation class ForceFlexibility : R|kotlin/Annotation| {
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class ForceFlexibility : R|kotlin/Annotation| {
public constructor(): R|spr/ForceFlexibility|
}
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public final annotation class NonNullApi : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|spr/NonNullApi|
}
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|(), R|kotlin/annotation/AnnotationTarget.FUNCTION|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_SETTER|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public final annotation class Nullable : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|(), R|kotlin/annotation/AnnotationTarget.FUNCTION|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_SETTER|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|kotlin/Annotation| {
public constructor(): R|spr/Nullable|
}
@R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) public final annotation class UnknownNullability : R|kotlin/Annotation| {
@R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) public abstract annotation class UnknownNullability : R|kotlin/Annotation| {
public constructor(): R|spr/UnknownNullability|
}

View File

@@ -20,15 +20,15 @@ public abstract interface B : R|kotlin/Any| {
public abstract fun foobar(@R|javax/annotation/Nonnull|() x: R|@EnhancedNullability kotlin/String|): R|kotlin/Unit|
}
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public final annotation class ForceFlexibility : R|kotlin/Annotation| {
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class ForceFlexibility : R|kotlin/Annotation| {
public constructor(): R|spr/ForceFlexibility|
}
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public final annotation class NonNullApi : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|spr/NonNullApi|
}
@R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) public final annotation class UnknownNullability : R|kotlin/Annotation| {
@R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) public abstract annotation class UnknownNullability : R|kotlin/Annotation| {
public constructor(): R|spr/UnknownNullability|
}

View File

@@ -54,11 +54,11 @@
public constructor(): R|C|
}
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public final annotation class NonNullApi : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|NonNullApi|
}
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public final annotation class NullableApi : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NullableApi : R|kotlin/Annotation| {
public constructor(): R|NullableApi|
}

View File

@@ -12,15 +12,15 @@
public constructor(): R|A|
}
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public final annotation class FieldsAreNullable : R|kotlin/Annotation| {
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class FieldsAreNullable : R|kotlin/Annotation| {
public constructor(): R|FieldsAreNullable|
}
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public final annotation class NonNullApi : R|kotlin/Annotation| {
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|NonNullApi|
}
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public final annotation class NullableApi : R|kotlin/Annotation| {
@R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NullableApi : R|kotlin/Annotation| {
public constructor(): R|NullableApi|
}

View File

@@ -10,11 +10,11 @@
public constructor(): R|A|
}
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public final annotation class NonNullApi : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|spr/NonNullApi|
}
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|(), R|kotlin/annotation/AnnotationTarget.FUNCTION|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_SETTER|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public final annotation class Nullable : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|(), R|kotlin/annotation/AnnotationTarget.FUNCTION|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_SETTER|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|kotlin/Annotation| {
public constructor(): R|spr/Nullable|
}

View File

@@ -10,11 +10,11 @@ public open class A : R|kotlin/Any| {
public constructor(): R|test/A|
}
@R|kotlin/annotation/Target|(<implicitArrayOf>()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public final annotation class NonNullApi : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(<implicitArrayOf>()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|spr/NonNullApi|
}
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|(), R|kotlin/annotation/AnnotationTarget.FUNCTION|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_SETTER|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public final annotation class Nullable : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|(), R|kotlin/annotation/AnnotationTarget.FUNCTION|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_SETTER|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|kotlin/Annotation| {
public constructor(): R|spr/Nullable|
}

View File

@@ -2,7 +2,7 @@ class StringBuilder {
fun append(s: String) {}
}
fun buildString(init: StringBuilder.() -> Unit): String {<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
fun buildString(init: StringBuilder.() -> Unit): String {}
interface Template<in X>

View File

@@ -18,10 +18,10 @@ fun test_2(n: Int) {
val y = n + 1
}
fun Int.bar(): Int {<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
fun Int.bar(): Int {}
fun Int.baz(): Int {<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
fun Byte.baz(): Byte {<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
fun Int.baz(): Int {}
fun Byte.baz(): Byte {}
fun test_3() {
val x = 1.bar()

View File

@@ -71,163 +71,162 @@ digraph flowFromInplaceLambda_kt {
21 [label="Enter block"];
22 [label="Const: Null(null)"];
23 [label="Check not null: Null(null)!!"];
24 [label="Stub" style="filled" fillcolor=gray];
25 [label="Jump: ^materialize Null(null)!!" style="filled" fillcolor=gray];
26 [label="Stub" style="filled" fillcolor=gray];
27 [label="Exit block" style="filled" fillcolor=gray];
24 [label="Jump: ^materialize Null(null)!!"];
25 [label="Stub" style="filled" fillcolor=gray];
26 [label="Exit block" style="filled" fillcolor=gray];
}
28 [label="Exit function materialize" style="filled" fillcolor=red];
27 [label="Exit function materialize" style="filled" fillcolor=red];
}
20 -> {21};
21 -> {22};
22 -> {23};
23 -> {28} [label=onUncaughtException];
23 -> {24} [style=dotted];
23 -> {24};
24 -> {27};
24 -> {25} [style=dotted];
25 -> {28 26} [style=dotted];
25 -> {26} [style=dotted];
26 -> {27} [style=dotted];
27 -> {28} [style=dotted];
subgraph cluster_8 {
color=red
29 [label="Enter function myRun" style="filled" fillcolor=red];
28 [label="Enter function myRun" style="filled" fillcolor=red];
subgraph cluster_9 {
color=blue
30 [label="Enter block"];
31 [label="Function call: R|<local>/block|.R|SubstitutionOverride<kotlin/Function0.invoke: R|R|>|()"];
32 [label="Jump: ^myRun R|<local>/block|.R|SubstitutionOverride<kotlin/Function0.invoke: R|R|>|()"];
33 [label="Stub" style="filled" fillcolor=gray];
34 [label="Exit block" style="filled" fillcolor=gray];
29 [label="Enter block"];
30 [label="Function call: R|<local>/block|.R|SubstitutionOverride<kotlin/Function0.invoke: R|R|>|()"];
31 [label="Jump: ^myRun R|<local>/block|.R|SubstitutionOverride<kotlin/Function0.invoke: R|R|>|()"];
32 [label="Stub" style="filled" fillcolor=gray];
33 [label="Exit block" style="filled" fillcolor=gray];
}
35 [label="Exit function myRun" style="filled" fillcolor=red];
34 [label="Exit function myRun" style="filled" fillcolor=red];
}
28 -> {29};
29 -> {30};
30 -> {31};
31 -> {32};
32 -> {35};
31 -> {34};
31 -> {32} [style=dotted];
32 -> {33} [style=dotted];
33 -> {34} [style=dotted];
34 -> {35} [style=dotted];
subgraph cluster_10 {
color=red
36 [label="Enter function test_1" style="filled" fillcolor=red];
35 [label="Enter function test_1" style="filled" fillcolor=red];
subgraph cluster_11 {
color=blue
37 [label="Enter block"];
38 [label="Postponed enter to lambda"];
36 [label="Enter block"];
37 [label="Postponed enter to lambda"];
subgraph cluster_12 {
color=blue
46 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
45 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_13 {
color=blue
47 [label="Enter block"];
48 [label="Access variable R|<local>/x|"];
49 [label="Type operator: (R|<local>/x| as R|kotlin/Int|)"];
50 [label="Exit block"];
46 [label="Enter block"];
47 [label="Access variable R|<local>/x|"];
48 [label="Type operator: (R|<local>/x| as R|kotlin/Int|)"];
49 [label="Exit block"];
}
51 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
50 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
39 [label="Call arguments union" style="filled" fillcolor=yellow];
40 [label="Postponed exit from lambda"];
41 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
42 [label="Access variable R|<local>/x|"];
43 [label="Function call: R|/takeInt|(...)"];
44 [label="Exit block"];
38 [label="Call arguments union" style="filled" fillcolor=yellow];
39 [label="Postponed exit from lambda"];
40 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
41 [label="Access variable R|<local>/x|"];
42 [label="Function call: R|/takeInt|(...)"];
43 [label="Exit block"];
}
45 [label="Exit function test_1" style="filled" fillcolor=red];
44 [label="Exit function test_1" style="filled" fillcolor=red];
}
35 -> {36};
36 -> {37};
37 -> {38};
38 -> {46};
37 -> {45};
37 -> {39} [color=red];
37 -> {45} [style=dashed];
38 -> {40} [color=red];
38 -> {46} [style=dashed];
39 -> {41} [color=red];
40 -> {41} [color=green];
39 -> {40} [color=green];
40 -> {41};
41 -> {42};
42 -> {43};
43 -> {44};
44 -> {45};
45 -> {46};
46 -> {47};
47 -> {48};
48 -> {49};
49 -> {50};
50 -> {51};
51 -> {39} [color=red];
51 -> {40} [color=green];
50 -> {38} [color=red];
50 -> {39} [color=green];
subgraph cluster_14 {
color=red
52 [label="Enter function test_2" style="filled" fillcolor=red];
51 [label="Enter function test_2" style="filled" fillcolor=red];
subgraph cluster_15 {
color=blue
53 [label="Enter block"];
54 [label="Postponed enter to lambda"];
52 [label="Enter block"];
53 [label="Postponed enter to lambda"];
subgraph cluster_16 {
color=blue
75 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
74 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_17 {
color=blue
76 [label="Enter block"];
77 [label="Access variable R|<local>/y|"];
78 [label="Function call: R|<local>/y|.<Unresolved name: inc>#()"];
79 [label="Access variable R|<local>/x|"];
80 [label="Type operator: (R|<local>/x| as R|kotlin/Int|)"];
81 [label="Exit block"];
75 [label="Enter block"];
76 [label="Access variable R|<local>/y|"];
77 [label="Function call: R|<local>/y|.<Unresolved name: inc>#()"];
78 [label="Access variable R|<local>/x|"];
79 [label="Type operator: (R|<local>/x| as R|kotlin/Int|)"];
80 [label="Exit block"];
}
82 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
81 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
55 [label="Postponed exit from lambda"];
56 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
57 [label="Call arguments union" style="filled" fillcolor=yellow];
58 [label="Function call: R|/id|<R|kotlin/Int|>(...)"];
59 [label="Access variable R|<local>/y|"];
60 [label="Type operator: (R|<local>/y| as R|kotlin/Int|)"];
61 [label="Postponed enter to lambda"];
54 [label="Postponed exit from lambda"];
55 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
56 [label="Call arguments union" style="filled" fillcolor=yellow];
57 [label="Function call: R|/id|<R|kotlin/Int|>(...)"];
58 [label="Access variable R|<local>/y|"];
59 [label="Type operator: (R|<local>/y| as R|kotlin/Int|)"];
60 [label="Postponed enter to lambda"];
subgraph cluster_18 {
color=blue
83 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
82 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_19 {
color=blue
84 [label="Enter block"];
85 [label="Access variable R|<local>/x|"];
86 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
87 [label="Access variable R|<local>/y|"];
88 [label="Function call: R|<local>/y|.R|kotlin/Int.inc|()"];
89 [label="Const: Int(1)"];
90 [label="Exit block"];
83 [label="Enter block"];
84 [label="Access variable R|<local>/x|"];
85 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
86 [label="Access variable R|<local>/y|"];
87 [label="Function call: R|<local>/y|.R|kotlin/Int.inc|()"];
88 [label="Const: Int(1)"];
89 [label="Exit block"];
}
91 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
90 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
62 [label="Postponed exit from lambda"];
63 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
64 [label="Call arguments union" style="filled" fillcolor=yellow];
65 [label="Function call: R|/select|<R|kotlin/Int|>(...)"];
66 [label="Variable declaration: lval a: R|kotlin/Int|"];
67 [label="Access variable R|<local>/x|"];
68 [label="Function call: R|/takeInt|(...)"];
69 [label="Access variable R|<local>/y|"];
70 [label="Function call: R|/takeInt|(...)"];
71 [label="Access variable R|<local>/a|"];
72 [label="Function call: R|/takeInt|(...)"];
73 [label="Exit block"];
61 [label="Postponed exit from lambda"];
62 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
63 [label="Call arguments union" style="filled" fillcolor=yellow];
64 [label="Function call: R|/select|<R|kotlin/Int|>(...)"];
65 [label="Variable declaration: lval a: R|kotlin/Int|"];
66 [label="Access variable R|<local>/x|"];
67 [label="Function call: R|/takeInt|(...)"];
68 [label="Access variable R|<local>/y|"];
69 [label="Function call: R|/takeInt|(...)"];
70 [label="Access variable R|<local>/a|"];
71 [label="Function call: R|/takeInt|(...)"];
72 [label="Exit block"];
}
74 [label="Exit function test_2" style="filled" fillcolor=red];
73 [label="Exit function test_2" style="filled" fillcolor=red];
}
51 -> {52};
52 -> {53};
53 -> {54};
54 -> {75};
54 -> {55} [color=red];
54 -> {75} [style=dashed];
53 -> {74};
53 -> {54} [color=red];
53 -> {74} [style=dashed];
54 -> {55};
55 -> {56};
56 -> {57};
57 -> {58};
58 -> {59};
59 -> {60};
60 -> {61};
61 -> {83};
61 -> {62} [color=red];
61 -> {83} [style=dashed];
60 -> {82};
60 -> {61} [color=red];
60 -> {82} [style=dashed];
61 -> {62};
62 -> {63};
63 -> {64};
64 -> {65};
@@ -239,16 +238,16 @@ digraph flowFromInplaceLambda_kt {
70 -> {71};
71 -> {72};
72 -> {73};
73 -> {74};
74 -> {75};
75 -> {76};
76 -> {77};
77 -> {78};
78 -> {79};
79 -> {80};
80 -> {81};
81 -> {82};
82 -> {57} [color=red];
82 -> {55} [color=green];
81 -> {56} [color=red];
81 -> {54} [color=green];
82 -> {83};
83 -> {84};
84 -> {85};
85 -> {86};
@@ -256,79 +255,79 @@ digraph flowFromInplaceLambda_kt {
87 -> {88};
88 -> {89};
89 -> {90};
90 -> {91};
91 -> {64} [color=red];
91 -> {62} [color=green];
90 -> {63} [color=red];
90 -> {61} [color=green];
subgraph cluster_20 {
color=red
92 [label="Enter function test_3" style="filled" fillcolor=red];
91 [label="Enter function test_3" style="filled" fillcolor=red];
subgraph cluster_21 {
color=blue
93 [label="Enter block"];
94 [label="Postponed enter to lambda"];
92 [label="Enter block"];
93 [label="Postponed enter to lambda"];
subgraph cluster_22 {
color=blue
112 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
111 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_23 {
color=blue
113 [label="Enter block"];
114 [label="Access variable R|<local>/y|"];
115 [label="Function call: R|<local>/y|.<Unresolved name: inc>#()"];
116 [label="Access variable R|<local>/x|"];
117 [label="Type operator: (R|<local>/x| as R|kotlin/Int|)"];
118 [label="Function call: R|/materialize|<R|kotlin/Int|>()"];
119 [label="Exit block"];
112 [label="Enter block"];
113 [label="Access variable R|<local>/y|"];
114 [label="Function call: R|<local>/y|.<Unresolved name: inc>#()"];
115 [label="Access variable R|<local>/x|"];
116 [label="Type operator: (R|<local>/x| as R|kotlin/Int|)"];
117 [label="Function call: R|/materialize|<R|kotlin/Int|>()"];
118 [label="Exit block"];
}
120 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
119 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
95 [label="Postponed exit from lambda"];
96 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
97 [label="Function call: R|/id|<R|kotlin/Int|>(...)"];
98 [label="Postponed enter to lambda"];
94 [label="Postponed exit from lambda"];
95 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
96 [label="Function call: R|/id|<R|kotlin/Int|>(...)"];
97 [label="Postponed enter to lambda"];
subgraph cluster_24 {
color=blue
121 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
120 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_25 {
color=blue
122 [label="Enter block"];
123 [label="Access variable R|<local>/y|"];
124 [label="Type operator: (R|<local>/y| as R|kotlin/Int|)"];
125 [label="Access variable R|<local>/x|"];
126 [label="Function call: R|<local>/x|.<Unresolved name: inc>#()"];
127 [label="Access variable R|<local>/y|"];
128 [label="Function call: R|<local>/y|.R|kotlin/Int.inc|()"];
129 [label="Const: Int(1)"];
130 [label="Exit block"];
121 [label="Enter block"];
122 [label="Access variable R|<local>/y|"];
123 [label="Type operator: (R|<local>/y| as R|kotlin/Int|)"];
124 [label="Access variable R|<local>/x|"];
125 [label="Function call: R|<local>/x|.<Unresolved name: inc>#()"];
126 [label="Access variable R|<local>/y|"];
127 [label="Function call: R|<local>/y|.R|kotlin/Int.inc|()"];
128 [label="Const: Int(1)"];
129 [label="Exit block"];
}
131 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
130 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
99 [label="Postponed exit from lambda"];
100 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
101 [label="Call arguments union" style="filled" fillcolor=yellow];
102 [label="Function call: R|/select|<R|kotlin/Int|>(...)"];
103 [label="Variable declaration: lval a: R|kotlin/Int|"];
104 [label="Access variable R|<local>/x|"];
105 [label="Function call: R|/takeInt|(...)"];
106 [label="Access variable R|<local>/y|"];
107 [label="Function call: R|/takeInt|(...)"];
108 [label="Access variable R|<local>/a|"];
109 [label="Function call: R|/takeInt|(...)"];
110 [label="Exit block"];
98 [label="Postponed exit from lambda"];
99 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
100 [label="Call arguments union" style="filled" fillcolor=yellow];
101 [label="Function call: R|/select|<R|kotlin/Int|>(...)"];
102 [label="Variable declaration: lval a: R|kotlin/Int|"];
103 [label="Access variable R|<local>/x|"];
104 [label="Function call: R|/takeInt|(...)"];
105 [label="Access variable R|<local>/y|"];
106 [label="Function call: R|/takeInt|(...)"];
107 [label="Access variable R|<local>/a|"];
108 [label="Function call: R|/takeInt|(...)"];
109 [label="Exit block"];
}
111 [label="Exit function test_3" style="filled" fillcolor=red];
110 [label="Exit function test_3" style="filled" fillcolor=red];
}
91 -> {92};
92 -> {93};
93 -> {94};
94 -> {112};
94 -> {95} [color=red];
94 -> {112} [style=dashed];
93 -> {111};
93 -> {94} [color=red];
93 -> {111} [style=dashed];
94 -> {95};
95 -> {96};
96 -> {97};
97 -> {98};
98 -> {121};
98 -> {99} [color=red];
98 -> {121} [style=dashed];
97 -> {120};
97 -> {98} [color=red];
97 -> {120} [style=dashed];
98 -> {99};
99 -> {100};
100 -> {101};
101 -> {102};
@@ -340,7 +339,7 @@ digraph flowFromInplaceLambda_kt {
107 -> {108};
108 -> {109};
109 -> {110};
110 -> {111};
111 -> {112};
112 -> {113};
113 -> {114};
114 -> {115};
@@ -348,9 +347,9 @@ digraph flowFromInplaceLambda_kt {
116 -> {117};
117 -> {118};
118 -> {119};
119 -> {120};
120 -> {101} [color=red];
120 -> {95} [color=green];
119 -> {100} [color=red];
119 -> {94} [color=green];
120 -> {121};
121 -> {122};
122 -> {123};
123 -> {124};
@@ -360,77 +359,77 @@ digraph flowFromInplaceLambda_kt {
127 -> {128};
128 -> {129};
129 -> {130};
130 -> {131};
131 -> {101} [color=red];
131 -> {99} [color=green];
130 -> {100} [color=red];
130 -> {98} [color=green];
subgraph cluster_26 {
color=red
132 [label="Enter function test_4" style="filled" fillcolor=red];
131 [label="Enter function test_4" style="filled" fillcolor=red];
subgraph cluster_27 {
color=blue
133 [label="Enter block"];
134 [label="Postponed enter to lambda"];
132 [label="Enter block"];
133 [label="Postponed enter to lambda"];
subgraph cluster_28 {
color=blue
153 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
152 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_29 {
color=blue
154 [label="Enter block"];
155 [label="Access variable R|<local>/y|"];
156 [label="Function call: R|<local>/y|.<Unresolved name: inc>#()"];
157 [label="Access variable R|<local>/x|"];
158 [label="Type operator: (R|<local>/x| as R|kotlin/Int|)"];
159 [label="Exit block"];
153 [label="Enter block"];
154 [label="Access variable R|<local>/y|"];
155 [label="Function call: R|<local>/y|.<Unresolved name: inc>#()"];
156 [label="Access variable R|<local>/x|"];
157 [label="Type operator: (R|<local>/x| as R|kotlin/Int|)"];
158 [label="Exit block"];
}
160 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
159 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
135 [label="Postponed exit from lambda"];
136 [label="Function call: R|/myRun|<R|kotlin/Int|>(...)"];
137 [label="Function call: R|/id|<R|kotlin/Int|>(...)"];
138 [label="Access variable R|<local>/y|"];
139 [label="Type operator: (R|<local>/y| as R|kotlin/Int|)"];
140 [label="Postponed enter to lambda"];
134 [label="Postponed exit from lambda"];
135 [label="Function call: R|/myRun|<R|kotlin/Int|>(...)"];
136 [label="Function call: R|/id|<R|kotlin/Int|>(...)"];
137 [label="Access variable R|<local>/y|"];
138 [label="Type operator: (R|<local>/y| as R|kotlin/Int|)"];
139 [label="Postponed enter to lambda"];
subgraph cluster_30 {
color=blue
161 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
160 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_31 {
color=blue
162 [label="Enter block"];
163 [label="Access variable R|<local>/x|"];
164 [label="Function call: R|<local>/x|.<Unresolved name: inc>#()"];
165 [label="Access variable R|<local>/y|"];
166 [label="Function call: R|<local>/y|.R|kotlin/Int.inc|()"];
167 [label="Const: Int(1)"];
168 [label="Exit block"];
161 [label="Enter block"];
162 [label="Access variable R|<local>/x|"];
163 [label="Function call: R|<local>/x|.<Unresolved name: inc>#()"];
164 [label="Access variable R|<local>/y|"];
165 [label="Function call: R|<local>/y|.R|kotlin/Int.inc|()"];
166 [label="Const: Int(1)"];
167 [label="Exit block"];
}
169 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
168 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
141 [label="Postponed exit from lambda"];
142 [label="Function call: R|/myRun|<R|kotlin/Int|>(...)"];
143 [label="Function call: R|/select|<R|kotlin/Int|>(...)"];
144 [label="Variable declaration: lval a: R|kotlin/Int|"];
145 [label="Access variable R|<local>/x|"];
146 [label="Function call: <Inapplicable(INAPPLICABLE): /takeInt>#(...)"];
147 [label="Access variable R|<local>/y|"];
148 [label="Function call: R|/takeInt|(...)"];
149 [label="Access variable R|<local>/a|"];
150 [label="Function call: R|/takeInt|(...)"];
151 [label="Exit block"];
140 [label="Postponed exit from lambda"];
141 [label="Function call: R|/myRun|<R|kotlin/Int|>(...)"];
142 [label="Function call: R|/select|<R|kotlin/Int|>(...)"];
143 [label="Variable declaration: lval a: R|kotlin/Int|"];
144 [label="Access variable R|<local>/x|"];
145 [label="Function call: <Inapplicable(INAPPLICABLE): /takeInt>#(...)"];
146 [label="Access variable R|<local>/y|"];
147 [label="Function call: R|/takeInt|(...)"];
148 [label="Access variable R|<local>/a|"];
149 [label="Function call: R|/takeInt|(...)"];
150 [label="Exit block"];
}
152 [label="Exit function test_4" style="filled" fillcolor=red];
151 [label="Exit function test_4" style="filled" fillcolor=red];
}
131 -> {132};
132 -> {133};
133 -> {134};
134 -> {135 153};
134 -> {153} [style=dashed];
133 -> {134 152};
133 -> {152} [style=dashed];
134 -> {135};
135 -> {136};
136 -> {137};
137 -> {138};
138 -> {139};
139 -> {140};
140 -> {141 161};
140 -> {161} [style=dashed];
139 -> {140 160};
139 -> {160} [style=dashed];
140 -> {141};
141 -> {142};
142 -> {143};
143 -> {144};
@@ -441,14 +440,14 @@ digraph flowFromInplaceLambda_kt {
148 -> {149};
149 -> {150};
150 -> {151};
151 -> {152};
152 -> {153};
153 -> {154};
154 -> {155};
155 -> {156};
156 -> {157};
157 -> {158};
158 -> {159};
159 -> {160};
160 -> {161};
161 -> {162};
162 -> {163};
163 -> {164};
@@ -456,61 +455,61 @@ digraph flowFromInplaceLambda_kt {
165 -> {166};
166 -> {167};
167 -> {168};
168 -> {169};
subgraph cluster_32 {
color=red
170 [label="Enter function test_5" style="filled" fillcolor=red];
169 [label="Enter function test_5" style="filled" fillcolor=red];
subgraph cluster_33 {
color=blue
171 [label="Enter block"];
172 [label="Postponed enter to lambda"];
170 [label="Enter block"];
171 [label="Postponed enter to lambda"];
subgraph cluster_34 {
color=blue
185 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
184 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_35 {
color=blue
186 [label="Enter block"];
187 [label="Function call: R|/materialize|<R|kotlin/Int|>()"];
188 [label="Exit block"];
185 [label="Enter block"];
186 [label="Function call: R|/materialize|<R|kotlin/Int|>()"];
187 [label="Exit block"];
}
189 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
188 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
173 [label="Postponed exit from lambda"];
174 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
175 [label="Postponed enter to lambda"];
172 [label="Postponed exit from lambda"];
173 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
174 [label="Postponed enter to lambda"];
subgraph cluster_36 {
color=blue
190 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
189 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_37 {
color=blue
191 [label="Enter block"];
192 [label="Function call: R|/materialize|<R|kotlin/Int|>()"];
193 [label="Exit block"];
190 [label="Enter block"];
191 [label="Function call: R|/materialize|<R|kotlin/Int|>()"];
192 [label="Exit block"];
}
194 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
193 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
176 [label="Postponed exit from lambda"];
177 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
178 [label="Call arguments union" style="filled" fillcolor=yellow];
179 [label="Function call: R|/select|<R|kotlin/Int|>(...)"];
180 [label="Variable declaration: lval x: R|kotlin/Int|"];
181 [label="Access variable R|<local>/x|"];
182 [label="Function call: R|/takeInt|(...)"];
183 [label="Exit block"];
175 [label="Postponed exit from lambda"];
176 [label="Function call: R|kotlin/run|<R|kotlin/Int|>(...)"];
177 [label="Call arguments union" style="filled" fillcolor=yellow];
178 [label="Function call: R|/select|<R|kotlin/Int|>(...)"];
179 [label="Variable declaration: lval x: R|kotlin/Int|"];
180 [label="Access variable R|<local>/x|"];
181 [label="Function call: R|/takeInt|(...)"];
182 [label="Exit block"];
}
184 [label="Exit function test_5" style="filled" fillcolor=red];
183 [label="Exit function test_5" style="filled" fillcolor=red];
}
169 -> {170};
170 -> {171};
171 -> {172};
172 -> {185};
172 -> {173} [color=red];
172 -> {185} [style=dashed];
171 -> {184};
171 -> {172} [color=red];
171 -> {184} [style=dashed];
172 -> {173};
173 -> {174};
174 -> {175};
175 -> {190};
175 -> {176} [color=red];
175 -> {190} [style=dashed];
174 -> {189};
174 -> {175} [color=red];
174 -> {189} [style=dashed];
175 -> {176};
176 -> {177};
177 -> {178};
178 -> {179};
@@ -518,80 +517,79 @@ digraph flowFromInplaceLambda_kt {
180 -> {181};
181 -> {182};
182 -> {183};
183 -> {184};
184 -> {185};
185 -> {186};
186 -> {187};
187 -> {188};
188 -> {189};
189 -> {178} [color=red];
189 -> {173} [color=green];
188 -> {177} [color=red];
188 -> {172} [color=green];
189 -> {190};
190 -> {191};
191 -> {192};
192 -> {193};
193 -> {194};
194 -> {178} [color=red];
194 -> {176} [color=green];
193 -> {177} [color=red];
193 -> {175} [color=green];
subgraph cluster_38 {
color=red
195 [label="Enter function test_6" style="filled" fillcolor=red];
194 [label="Enter function test_6" style="filled" fillcolor=red];
subgraph cluster_39 {
color=blue
196 [label="Enter block"];
197 [label="Postponed enter to lambda"];
195 [label="Enter block"];
196 [label="Postponed enter to lambda"];
subgraph cluster_40 {
color=blue
204 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
203 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_41 {
color=blue
205 [label="Enter block"];
206 [label="Postponed enter to lambda"];
204 [label="Enter block"];
205 [label="Postponed enter to lambda"];
subgraph cluster_42 {
color=blue
211 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
210 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_43 {
color=blue
212 [label="Enter block"];
213 [label="Function call: R|/materialize|<R|kotlin/String|>()"];
214 [label="Exit block"];
211 [label="Enter block"];
212 [label="Function call: R|/materialize|<R|kotlin/String|>()"];
213 [label="Exit block"];
}
215 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
214 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
207 [label="Postponed exit from lambda"];
208 [label="Function call: R|kotlin/run|<R|kotlin/String|>(...)"];
209 [label="Exit block"];
206 [label="Postponed exit from lambda"];
207 [label="Function call: R|kotlin/run|<R|kotlin/String|>(...)"];
208 [label="Exit block"];
}
210 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
209 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
198 [label="Postponed exit from lambda"];
199 [label="Function call: R|/myRun|<R|kotlin/String|>(...)"];
200 [label="Function call: R|/id|<R|kotlin/String|>(...)"];
201 [label="Variable declaration: lval x: R|kotlin/String|"];
202 [label="Exit block"];
197 [label="Postponed exit from lambda"];
198 [label="Function call: R|/myRun|<R|kotlin/String|>(...)"];
199 [label="Function call: R|/id|<R|kotlin/String|>(...)"];
200 [label="Variable declaration: lval x: R|kotlin/String|"];
201 [label="Exit block"];
}
203 [label="Exit function test_6" style="filled" fillcolor=red];
202 [label="Exit function test_6" style="filled" fillcolor=red];
}
194 -> {195};
195 -> {196};
196 -> {197};
197 -> {198 204};
197 -> {204} [style=dashed];
196 -> {197 203};
196 -> {203} [style=dashed];
197 -> {198};
198 -> {199};
199 -> {200};
200 -> {201};
201 -> {202};
202 -> {203};
203 -> {204};
204 -> {205};
205 -> {206};
206 -> {211};
206 -> {207} [color=red];
206 -> {211} [style=dashed];
205 -> {210};
205 -> {206} [color=red];
205 -> {210} [style=dashed];
206 -> {207};
207 -> {208};
208 -> {209};
209 -> {210};
210 -> {211};
211 -> {212};
212 -> {213};
213 -> {214};
214 -> {215};
215 -> {207} [color=green];
214 -> {206} [color=green];
}

View File

@@ -11,176 +11,175 @@ digraph inplaceLambdaInControlFlowExpressions_kt {
1 [label="Enter block"];
2 [label="Const: Null(null)"];
3 [label="Check not null: Null(null)!!"];
4 [label="Stub" style="filled" fillcolor=gray];
5 [label="Jump: ^materialize Null(null)!!" style="filled" fillcolor=gray];
6 [label="Stub" style="filled" fillcolor=gray];
7 [label="Exit block" style="filled" fillcolor=gray];
4 [label="Jump: ^materialize Null(null)!!"];
5 [label="Stub" style="filled" fillcolor=gray];
6 [label="Exit block" style="filled" fillcolor=gray];
}
8 [label="Exit function materialize" style="filled" fillcolor=red];
7 [label="Exit function materialize" style="filled" fillcolor=red];
}
0 -> {1};
1 -> {2};
2 -> {3};
3 -> {8} [label=onUncaughtException];
3 -> {4} [style=dotted];
3 -> {4};
4 -> {7};
4 -> {5} [style=dotted];
5 -> {8 6} [style=dotted];
5 -> {6} [style=dotted];
6 -> {7} [style=dotted];
7 -> {8} [style=dotted];
subgraph cluster_2 {
color=red
9 [label="Enter function test_1" style="filled" fillcolor=red];
8 [label="Enter function test_1" style="filled" fillcolor=red];
subgraph cluster_3 {
color=blue
10 [label="Enter block"];
9 [label="Enter block"];
subgraph cluster_4 {
color=blue
11 [label="Enter when"];
10 [label="Enter when"];
subgraph cluster_5 {
color=blue
12 [label="Enter when branch condition "];
13 [label="Const: Boolean(true)"];
14 [label="Exit when branch condition"];
11 [label="Enter when branch condition "];
12 [label="Const: Boolean(true)"];
13 [label="Exit when branch condition"];
}
subgraph cluster_6 {
color=blue
15 [label="Enter when branch condition else"];
16 [label="Exit when branch condition"];
14 [label="Enter when branch condition else"];
15 [label="Exit when branch condition"];
}
17 [label="Enter when branch result"];
16 [label="Enter when branch result"];
subgraph cluster_7 {
color=blue
18 [label="Enter block"];
19 [label="Const: String()"];
20 [label="Exit block"];
17 [label="Enter block"];
18 [label="Const: String()"];
19 [label="Exit block"];
}
21 [label="Exit when branch result"];
22 [label="Enter when branch result"];
20 [label="Exit when branch result"];
21 [label="Enter when branch result"];
subgraph cluster_8 {
color=blue
23 [label="Enter block"];
24 [label="Postponed enter to lambda"];
22 [label="Enter block"];
23 [label="Postponed enter to lambda"];
subgraph cluster_9 {
color=blue
33 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
32 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_10 {
color=blue
34 [label="Enter block"];
35 [label="Function call: R|/materialize|<R|kotlin/String|>()"];
36 [label="Exit block"];
33 [label="Enter block"];
34 [label="Function call: R|/materialize|<R|kotlin/String|>()"];
35 [label="Exit block"];
}
37 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
36 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
25 [label="Postponed exit from lambda"];
26 [label="Function call: R|kotlin/run|<R|kotlin/String|>(...)"];
27 [label="Exit block"];
24 [label="Postponed exit from lambda"];
25 [label="Function call: R|kotlin/run|<R|kotlin/String|>(...)"];
26 [label="Exit block"];
}
28 [label="Exit when branch result"];
29 [label="Exit when"];
27 [label="Exit when branch result"];
28 [label="Exit when"];
}
30 [label="Variable declaration: lval x: R|kotlin/String|"];
31 [label="Exit block"];
29 [label="Variable declaration: lval x: R|kotlin/String|"];
30 [label="Exit block"];
}
32 [label="Exit function test_1" style="filled" fillcolor=red];
31 [label="Exit function test_1" style="filled" fillcolor=red];
}
8 -> {9};
9 -> {10};
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {14};
14 -> {22 15};
13 -> {21 14};
14 -> {15};
15 -> {16};
16 -> {17};
17 -> {18};
18 -> {19};
19 -> {20};
20 -> {21};
21 -> {29};
20 -> {28};
21 -> {22};
22 -> {23};
23 -> {24};
24 -> {33};
24 -> {25} [color=red];
24 -> {33} [style=dashed];
23 -> {32};
23 -> {24} [color=red];
23 -> {32} [style=dashed];
24 -> {25};
25 -> {26};
26 -> {27};
27 -> {28};
28 -> {29};
29 -> {30};
30 -> {31};
31 -> {32};
32 -> {33};
33 -> {34};
34 -> {35};
35 -> {36};
36 -> {37};
37 -> {25} [color=green];
36 -> {24} [color=green];
subgraph cluster_11 {
color=red
38 [label="Enter function test_2" style="filled" fillcolor=red];
37 [label="Enter function test_2" style="filled" fillcolor=red];
subgraph cluster_12 {
color=blue
39 [label="Enter block"];
38 [label="Enter block"];
subgraph cluster_13 {
color=blue
40 [label="Try expression enter"];
39 [label="Try expression enter"];
subgraph cluster_14 {
color=blue
41 [label="Try main block enter"];
40 [label="Try main block enter"];
subgraph cluster_15 {
color=blue
42 [label="Enter block"];
43 [label="Postponed enter to lambda"];
41 [label="Enter block"];
42 [label="Postponed enter to lambda"];
subgraph cluster_16 {
color=blue
58 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
57 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_17 {
color=blue
59 [label="Enter block"];
60 [label="Function call: R|/materialize|<R|kotlin/String|>()"];
61 [label="Exit block"];
58 [label="Enter block"];
59 [label="Function call: R|/materialize|<R|kotlin/String|>()"];
60 [label="Exit block"];
}
62 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
61 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
44 [label="Postponed exit from lambda"];
45 [label="Function call: R|kotlin/run|<R|kotlin/String|>(...)"];
46 [label="Exit block"];
43 [label="Postponed exit from lambda"];
44 [label="Function call: R|kotlin/run|<R|kotlin/String|>(...)"];
45 [label="Exit block"];
}
47 [label="Try main block exit"];
46 [label="Try main block exit"];
}
subgraph cluster_18 {
color=blue
48 [label="Catch enter"];
47 [label="Catch enter"];
subgraph cluster_19 {
color=blue
49 [label="Enter block"];
50 [label="Const: String()"];
51 [label="Exit block"];
48 [label="Enter block"];
49 [label="Const: String()"];
50 [label="Exit block"];
}
52 [label="Catch exit"];
51 [label="Catch exit"];
}
53 [label="Try expression exit"];
52 [label="Try expression exit"];
}
54 [label="Call arguments union" style="filled" fillcolor=yellow];
55 [label="Variable declaration: lval x: R|kotlin/String|"];
56 [label="Exit block"];
53 [label="Call arguments union" style="filled" fillcolor=yellow];
54 [label="Variable declaration: lval x: R|kotlin/String|"];
55 [label="Exit block"];
}
57 [label="Exit function test_2" style="filled" fillcolor=red];
56 [label="Exit function test_2" style="filled" fillcolor=red];
}
37 -> {38};
38 -> {39};
39 -> {40};
40 -> {41 48};
39 -> {40 47};
40 -> {41};
41 -> {42};
42 -> {43};
43 -> {58};
43 -> {44} [color=red];
43 -> {58} [style=dashed];
42 -> {57};
42 -> {43} [color=red];
42 -> {57} [style=dashed];
43 -> {44};
44 -> {45};
45 -> {46};
46 -> {47};
47 -> {53 48};
46 -> {52 47};
47 -> {48};
47 -> {56} [label=onUncaughtException];
48 -> {49};
48 -> {57} [label=onUncaughtException];
49 -> {50};
50 -> {51};
51 -> {52};
@@ -188,57 +187,56 @@ digraph inplaceLambdaInControlFlowExpressions_kt {
53 -> {54};
54 -> {55};
55 -> {56};
56 -> {57};
57 -> {58};
58 -> {59};
59 -> {60};
60 -> {61};
61 -> {62};
62 -> {54} [color=red];
62 -> {44} [color=green];
61 -> {53} [color=red];
61 -> {43} [color=green];
subgraph cluster_20 {
color=red
63 [label="Enter function test_3" style="filled" fillcolor=red];
62 [label="Enter function test_3" style="filled" fillcolor=red];
subgraph cluster_21 {
color=blue
64 [label="Enter block"];
65 [label="Postponed enter to lambda"];
63 [label="Enter block"];
64 [label="Postponed enter to lambda"];
subgraph cluster_22 {
color=blue
73 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
72 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_23 {
color=blue
74 [label="Enter block"];
75 [label="Function call: R|/materialize|<R|kotlin/String?|>()"];
76 [label="Exit block"];
73 [label="Enter block"];
74 [label="Function call: R|/materialize|<R|kotlin/String?|>()"];
75 [label="Exit block"];
}
77 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
76 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
66 [label="Postponed exit from lambda"];
67 [label="Function call: R|kotlin/run|<R|kotlin/String?|>(...)"];
68 [label="Check not null: R|kotlin/run|<R|kotlin/String?|>(...)!!"];
69 [label="Call arguments union" style="filled" fillcolor=yellow];
70 [label="Variable declaration: lval x: R|kotlin/String|"];
71 [label="Exit block"];
65 [label="Postponed exit from lambda"];
66 [label="Function call: R|kotlin/run|<R|kotlin/String?|>(...)"];
67 [label="Check not null: R|kotlin/run|<R|kotlin/String?|>(...)!!"];
68 [label="Call arguments union" style="filled" fillcolor=yellow];
69 [label="Variable declaration: lval x: R|kotlin/String|"];
70 [label="Exit block"];
}
72 [label="Exit function test_3" style="filled" fillcolor=red];
71 [label="Exit function test_3" style="filled" fillcolor=red];
}
62 -> {63};
63 -> {64};
64 -> {65};
65 -> {73};
65 -> {66} [color=red];
65 -> {73} [style=dashed];
64 -> {72};
64 -> {65} [color=red];
64 -> {72} [style=dashed];
65 -> {66};
66 -> {67};
67 -> {68};
68 -> {69};
69 -> {70};
70 -> {71};
71 -> {72};
72 -> {73};
73 -> {74};
74 -> {75};
75 -> {76};
76 -> {77};
77 -> {69} [color=red];
77 -> {66} [color=green];
76 -> {68} [color=red];
76 -> {65} [color=green];
}

View File

@@ -22,5 +22,5 @@ class KClassValue(value: Value) : ConstantValue<KClassValue.Value>(value) {
val (classId, arrayDimensions) = value.value
}
}
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
}
}

View File

@@ -1,14 +1,14 @@
package rest
abstract class Foo<T> {
abstract val x: T<!TYPE_ARGUMENTS_NOT_ALLOWED!><Int><!>
abstract val x: <!TYPE_ARGUMENTS_NOT_ALLOWED!>T<Int><!>
abstract fun foo(): T<!TYPE_ARGUMENTS_NOT_ALLOWED!><String><!>
abstract fun foo(): <!TYPE_ARGUMENTS_NOT_ALLOWED!>T<String><!>
}
fun <T> foo() {
bar<T<!TYPE_ARGUMENTS_NOT_ALLOWED!><Int><!>>()
bar<List<List<T<!TYPE_ARGUMENTS_NOT_ALLOWED!><Boolean><!>>>>()
bar<<!TYPE_ARGUMENTS_NOT_ALLOWED!>T<Int><!>>()
bar<List<List<<!TYPE_ARGUMENTS_NOT_ALLOWED!>T<Boolean><!>>>>()
}
fun <T> bar() {}
@@ -26,9 +26,9 @@ class C<F<!SYNTAX!><<!><!SYNTAX!>Boolean<!><!SYNTAX!>><!><!SYNTAX!>><!> <!SYNTAX
fun <G> gest() {}
fun <T> fest() {
val b: List<T<!TYPE_ARGUMENTS_NOT_ALLOWED!><Double><!>>
gest<T<!TYPE_ARGUMENTS_NOT_ALLOWED!><Char><!>>()
val b: List<<!TYPE_ARGUMENTS_NOT_ALLOWED!>T<Double><!>>
gest<<!TYPE_ARGUMENTS_NOT_ALLOWED!>T<Char><!>>()
gest<T>()
val c: List<List<List<T<!TYPE_ARGUMENTS_NOT_ALLOWED!><String><!>>>>
gest<List<List<T<!TYPE_ARGUMENTS_NOT_ALLOWED!><Boolean><!>>>>()
val c: List<List<List<<!TYPE_ARGUMENTS_NOT_ALLOWED!>T<String><!>>>>
gest<List<List<<!TYPE_ARGUMENTS_NOT_ALLOWED!>T<Boolean><!>>>>()
}

View File

@@ -27,7 +27,7 @@ fun test_2(cond: Boolean?) {
}
fun test_3(cond: Boolean) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (cond) {
when (cond) {
true -> 1
}
}

View File

@@ -27,7 +27,7 @@ fun test_2(enum: SomeEnum?) {
}
fun test_3(enum: SomeEnum) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (enum) {
when (enum) {
SomeEnum.A -> 1
}
}

View File

@@ -44,7 +44,7 @@ fun test_2(base: Base?) {
}
fun test_3(base: Base) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (base) {
when (base) {
is A -> 1
}
}

View File

@@ -1,5 +1,5 @@
class Foo {
operator fun plus(f: Foo): Foo {<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
operator fun plus(f: Foo): Foo {}
operator fun plusAssign(f: Foo) {}
}

View File

@@ -38,6 +38,10 @@ FILE: RedundantModalityModifierChecker.kt
public abstract interface Foo : R|kotlin/Any| {
}
public abstract expect class AbstractClass : R|Foo| {
public expect constructor(): R|AbstractClass| {
super<R|kotlin/Any|>()
}
public abstract expect override fun foo(): R|kotlin/Unit|
public abstract expect fun bar(): R|kotlin/Unit|

View File

@@ -2,7 +2,7 @@ fun <T> simpleRun(f: (T) -> Unit): Unit = f(<!RETURN_IN_FUNCTION_WITH_EXPRESSION
fun <T, R> List<T>.simpleMap(f: (T) -> R): R {
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
}
fun <T> simpleWith(t: T, f: T.() -> Unit): Unit = t.f()

View File

@@ -1,5 +1,5 @@
FILE: inlineClassConstructor.kt
public final inline class WithoutConstructor : R|kotlin/Any| {
public final class WithoutConstructor : R|kotlin/Any| {
public constructor(): R|WithoutConstructor| {
super<R|kotlin/Any|>()
}

View File

@@ -27,7 +27,7 @@ FILE: inlineClassDeclaration.kt
}
public final inner inline class D : R|kotlin/Any| {
public final inner class D : R|kotlin/Any| {
public constructor(x: R|kotlin/Int|): R|A.D| {
super<R|kotlin/Any|>()
}
@@ -65,7 +65,7 @@ FILE: inlineClassDeclaration.kt
public get(): R|kotlin/Int|
}
public final inline class CloneableClass1 : R|kotlin/Cloneable| {
public final class CloneableClass1 : R|kotlin/Cloneable| {
public constructor(x: R|kotlin/Int|): R|CloneableClass1| {
super<R|kotlin/Any|>()
}

View File

@@ -1,5 +1,5 @@
FILE: inlineClassMembers.kt
public final inline class BackingFields : R|kotlin/Any| {
public final class BackingFields : R|kotlin/Any| {
public constructor(x: R|kotlin/Int|): R|BackingFields| {
super<R|kotlin/Any|>()
}
@@ -82,7 +82,7 @@ FILE: inlineClassMembers.kt
}
}
public final inline class WithInner : R|kotlin/Any| {
public final class WithInner : R|kotlin/Any| {
public constructor(x: R|kotlin/String|): R|WithInner| {
super<R|kotlin/Any|>()
}

View File

@@ -2,6 +2,10 @@ FILE: B.kt
public abstract expect interface Other : R|kotlin/Any| {
}
public final expect class Another : R|kotlin/Any| {
public expect constructor(): R|b/d/Another| {
super<R|kotlin/Any|>()
}
}
public final fun baz(): R|kotlin/Unit| {
}

View File

@@ -32,7 +32,7 @@ class NamedCompilerPhase<in Context : CommonBackendContext, Data>(
}
}
runAfter(phaseConfig, phaserState, context, output)
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
}
private fun runAfter(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, output: Data) {
@@ -40,5 +40,5 @@ class NamedCompilerPhase<in Context : CommonBackendContext, Data>(
private fun runAndProfile(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, source: Data): Data {
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
}
}
}

View File

@@ -33,7 +33,7 @@ public interface Klass extends TypeParametersOwner {
fun List<String>.single(): String = ""
fun List<Int>.single(): Int = 2
fun listOf(): List<String> {<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
fun listOf(): List<String> {}
public open class LightMember<D> : Member<D>, Light() {
override fun getName(): String = "Light"

View File

@@ -61,9 +61,7 @@ digraph elvis_kt {
5 -> {6};
6 -> {7};
7 -> {8};
8 -> {9};
8 -> {11} [color=red];
8 -> {13} [color=green];
8 -> {9 11};
9 -> {10};
10 -> {11};
11 -> {12};

View File

@@ -469,9 +469,7 @@ digraph returns_kt {
151 -> {152};
152 -> {153};
153 -> {154};
154 -> {155};
154 -> {157} [color=red];
154 -> {159} [color=green];
154 -> {155 157};
155 -> {156};
156 -> {157};
157 -> {158};

View File

@@ -583,9 +583,7 @@ digraph nullability_kt {
194 -> {195 197};
195 -> {196};
196 -> {197};
197 -> {198};
197 -> {200} [color=red];
197 -> {202} [color=green];
197 -> {198 200};
198 -> {199};
199 -> {200};
200 -> {201};

View File

@@ -99,158 +99,157 @@ digraph smartcastToNothing_kt {
31 [label="Enter block"];
32 [label="Const: Null(null)"];
33 [label="Check not null: Null(null)!!"];
34 [label="Stub" style="filled" fillcolor=gray];
35 [label="Jump: ^myListOf Null(null)!!" style="filled" fillcolor=gray];
36 [label="Stub" style="filled" fillcolor=gray];
37 [label="Exit block" style="filled" fillcolor=gray];
34 [label="Jump: ^myListOf Null(null)!!"];
35 [label="Stub" style="filled" fillcolor=gray];
36 [label="Exit block" style="filled" fillcolor=gray];
}
38 [label="Exit function myListOf" style="filled" fillcolor=red];
37 [label="Exit function myListOf" style="filled" fillcolor=red];
}
30 -> {31};
31 -> {32};
32 -> {33};
33 -> {38} [label=onUncaughtException];
33 -> {34} [style=dotted];
33 -> {34};
34 -> {37};
34 -> {35} [style=dotted];
35 -> {38 36} [style=dotted];
35 -> {36} [style=dotted];
36 -> {37} [style=dotted];
37 -> {38} [style=dotted];
subgraph cluster_10 {
color=red
39 [label="Enter function <init>" style="filled" fillcolor=red];
40 [label="Delegated constructor call: super<R|kotlin/Any|>()"];
41 [label="Exit function <init>" style="filled" fillcolor=red];
38 [label="Enter function <init>" style="filled" fillcolor=red];
39 [label="Delegated constructor call: super<R|kotlin/Any|>()"];
40 [label="Exit function <init>" style="filled" fillcolor=red];
}
38 -> {39};
39 -> {40};
40 -> {41};
subgraph cluster_11 {
color=red
42 [label="Enter property" style="filled" fillcolor=red];
43 [label="Const: Int(1)"];
44 [label="Exit property" style="filled" fillcolor=red];
41 [label="Enter property" style="filled" fillcolor=red];
42 [label="Const: Int(1)"];
43 [label="Exit property" style="filled" fillcolor=red];
}
41 -> {42};
42 -> {43};
43 -> {44};
44 -> {50} [color=green];
43 -> {49} [color=green];
subgraph cluster_12 {
color=red
45 [label="Enter property" style="filled" fillcolor=red];
46 [label="Const: Boolean(true)"];
47 [label="Exit property" style="filled" fillcolor=red];
44 [label="Enter property" style="filled" fillcolor=red];
45 [label="Const: Boolean(true)"];
46 [label="Exit property" style="filled" fillcolor=red];
}
44 -> {45};
45 -> {46};
46 -> {47};
47 -> {51} [color=green];
46 -> {50} [color=green];
subgraph cluster_13 {
color=red
48 [label="Enter class A" style="filled" fillcolor=red];
47 [label="Enter class A" style="filled" fillcolor=red];
48 [label="Part of class initialization"];
49 [label="Part of class initialization"];
50 [label="Part of class initialization"];
51 [label="Exit class A" style="filled" fillcolor=red];
50 [label="Exit class A" style="filled" fillcolor=red];
}
48 -> {49} [color=green];
47 -> {48} [color=green];
48 -> {49} [style=dotted];
48 -> {41} [color=green];
48 -> {41} [style=dashed];
49 -> {50} [style=dotted];
49 -> {42} [color=green];
49 -> {42} [style=dashed];
50 -> {51} [style=dotted];
50 -> {45} [color=green];
50 -> {45} [style=dashed];
49 -> {44} [color=green];
49 -> {44} [style=dashed];
subgraph cluster_14 {
color=red
52 [label="Enter function test_0" style="filled" fillcolor=red];
51 [label="Enter function test_0" style="filled" fillcolor=red];
subgraph cluster_15 {
color=blue
53 [label="Enter block"];
54 [label="Const: Null(null)"];
55 [label="Variable declaration: lvar s: R|A?|"];
52 [label="Enter block"];
53 [label="Const: Null(null)"];
54 [label="Variable declaration: lvar s: R|A?|"];
subgraph cluster_16 {
color=blue
56 [label="Enter block"];
57 [label="Access variable R|<local>/results|"];
58 [label="Function call: R|<local>/results|.R|SubstitutionOverride<kotlin/collections/List.iterator: R|kotlin/collections/Iterator<kotlin/Nothing>|>|()"];
59 [label="Variable declaration: lval <iterator>: R|kotlin/collections/Iterator<kotlin/Nothing>|"];
55 [label="Enter block"];
56 [label="Access variable R|<local>/results|"];
57 [label="Function call: R|<local>/results|.R|SubstitutionOverride<kotlin/collections/List.iterator: R|kotlin/collections/Iterator<kotlin/Nothing>|>|()"];
58 [label="Variable declaration: lval <iterator>: R|kotlin/collections/Iterator<kotlin/Nothing>|"];
subgraph cluster_17 {
color=blue
60 [label="Enter while loop"];
59 [label="Enter while loop"];
subgraph cluster_18 {
color=blue
61 [label="Enter loop condition"];
62 [label="Access variable R|<local>/<iterator>|"];
63 [label="Function call: R|<local>/<iterator>|.R|kotlin/collections/Iterator.hasNext|()"];
64 [label="Exit loop condition"];
60 [label="Enter loop condition"];
61 [label="Access variable R|<local>/<iterator>|"];
62 [label="Function call: R|<local>/<iterator>|.R|kotlin/collections/Iterator.hasNext|()"];
63 [label="Exit loop condition"];
}
subgraph cluster_19 {
color=blue
65 [label="Enter loop block"];
64 [label="Enter loop block"];
subgraph cluster_20 {
color=blue
66 [label="Enter block"];
67 [label="Access variable R|<local>/<iterator>|"];
68 [label="Function call: R|<local>/<iterator>|.R|SubstitutionOverride<kotlin/collections/Iterator.next: R|kotlin/Nothing|>|()"];
69 [label="Stub" style="filled" fillcolor=gray];
70 [label="Variable declaration: lval result: R|kotlin/Nothing|" style="filled" fillcolor=gray];
71 [label="Access variable R|<local>/result|" style="filled" fillcolor=gray];
72 [label="Stub" style="filled" fillcolor=gray];
73 [label="Assignment: R|<local>/s|" style="filled" fillcolor=gray];
65 [label="Enter block"];
66 [label="Access variable R|<local>/<iterator>|"];
67 [label="Function call: R|<local>/<iterator>|.R|SubstitutionOverride<kotlin/collections/Iterator.next: R|kotlin/Nothing|>|()"];
68 [label="Stub" style="filled" fillcolor=gray];
69 [label="Variable declaration: lval result: R|kotlin/Nothing|" style="filled" fillcolor=gray];
70 [label="Access variable R|<local>/result|" style="filled" fillcolor=gray];
71 [label="Stub" style="filled" fillcolor=gray];
72 [label="Assignment: R|<local>/s|" style="filled" fillcolor=gray];
subgraph cluster_21 {
color=blue
74 [label="Enter when" style="filled" fillcolor=gray];
73 [label="Enter when" style="filled" fillcolor=gray];
subgraph cluster_22 {
color=blue
75 [label="Enter when branch condition " style="filled" fillcolor=gray];
76 [label="Access variable R|<local>/result|" style="filled" fillcolor=gray];
77 [label="Stub" style="filled" fillcolor=gray];
78 [label="Access variable <Unresolved name: b>#" style="filled" fillcolor=gray];
79 [label="Exit when branch condition" style="filled" fillcolor=gray];
74 [label="Enter when branch condition " style="filled" fillcolor=gray];
75 [label="Access variable R|<local>/result|" style="filled" fillcolor=gray];
76 [label="Stub" style="filled" fillcolor=gray];
77 [label="Access variable <Unresolved name: b>#" style="filled" fillcolor=gray];
78 [label="Exit when branch condition" style="filled" fillcolor=gray];
}
80 [label="Synthetic else branch" style="filled" fillcolor=gray];
81 [label="Enter when branch result" style="filled" fillcolor=gray];
79 [label="Synthetic else branch" style="filled" fillcolor=gray];
80 [label="Enter when branch result" style="filled" fillcolor=gray];
subgraph cluster_23 {
color=blue
82 [label="Enter block" style="filled" fillcolor=gray];
83 [label="Jump: break@@@[R|<local>/<iterator>|.R|kotlin/collections/Iterator.hasNext|()] " style="filled" fillcolor=gray];
84 [label="Stub" style="filled" fillcolor=gray];
85 [label="Exit block" style="filled" fillcolor=gray];
81 [label="Enter block" style="filled" fillcolor=gray];
82 [label="Jump: break@@@[R|<local>/<iterator>|.R|kotlin/collections/Iterator.hasNext|()] " style="filled" fillcolor=gray];
83 [label="Stub" style="filled" fillcolor=gray];
84 [label="Exit block" style="filled" fillcolor=gray];
}
86 [label="Exit when branch result" style="filled" fillcolor=gray];
87 [label="Exit when" style="filled" fillcolor=gray];
85 [label="Exit when branch result" style="filled" fillcolor=gray];
86 [label="Exit when" style="filled" fillcolor=gray];
}
88 [label="Exit block" style="filled" fillcolor=gray];
87 [label="Exit block" style="filled" fillcolor=gray];
}
89 [label="Exit loop block" style="filled" fillcolor=gray];
88 [label="Exit loop block" style="filled" fillcolor=gray];
}
90 [label="Exit whileloop"];
89 [label="Exit whileloop"];
}
91 [label="Exit block"];
90 [label="Exit block"];
}
92 [label="Access variable R|<local>/s|"];
93 [label="Enter safe call"];
94 [label="Postponed enter to lambda"];
91 [label="Access variable R|<local>/s|"];
92 [label="Enter safe call"];
93 [label="Postponed enter to lambda"];
subgraph cluster_24 {
color=blue
101 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
100 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
subgraph cluster_25 {
color=blue
102 [label="Enter block"];
103 [label="Access variable R|<local>/it|"];
104 [label="Access variable R|/A.a|"];
105 [label="Exit block"];
101 [label="Enter block"];
102 [label="Access variable R|<local>/it|"];
103 [label="Access variable R|/A.a|"];
104 [label="Exit block"];
}
106 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
105 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
95 [label="Call arguments union" style="filled" fillcolor=yellow];
96 [label="Postponed exit from lambda"];
97 [label="Function call: $subj$.R|kotlin/let|<R|A|, R|kotlin/Int|>(...)"];
98 [label="Exit safe call"];
99 [label="Exit block"];
94 [label="Call arguments union" style="filled" fillcolor=yellow];
95 [label="Postponed exit from lambda"];
96 [label="Function call: $subj$.R|kotlin/let|<R|A|, R|kotlin/Int|>(...)"];
97 [label="Exit safe call"];
98 [label="Exit block"];
}
100 [label="Exit function test_0" style="filled" fillcolor=red];
99 [label="Exit function test_0" style="filled" fillcolor=red];
}
51 -> {52};
52 -> {53};
53 -> {54};
54 -> {55};
@@ -262,54 +261,53 @@ digraph smartcastToNothing_kt {
60 -> {61};
61 -> {62};
62 -> {63};
63 -> {64};
64 -> {90 65};
63 -> {89 64};
64 -> {65};
65 -> {66};
66 -> {67};
67 -> {68};
68 -> {100} [label=onUncaughtException];
67 -> {99} [label=onUncaughtException];
67 -> {68} [style=dotted];
68 -> {69} [style=dotted];
69 -> {70} [style=dotted];
70 -> {71} [style=dotted];
70 -> {99} [style=dotted] [label=onUncaughtException];
71 -> {72} [style=dotted];
71 -> {100} [style=dotted] [label=onUncaughtException];
72 -> {73} [style=dotted];
73 -> {74} [style=dotted];
74 -> {75} [style=dotted];
75 -> {76} [style=dotted];
75 -> {99} [style=dotted] [label=onUncaughtException];
76 -> {77} [style=dotted];
76 -> {100} [style=dotted] [label=onUncaughtException];
77 -> {78} [style=dotted];
78 -> {79} [style=dotted];
79 -> {81 80} [style=dotted];
80 -> {87} [style=dotted];
78 -> {80 79} [style=dotted];
79 -> {86} [style=dotted];
80 -> {81} [style=dotted];
81 -> {82} [style=dotted];
82 -> {83} [style=dotted];
83 -> {90 84} [style=dotted];
82 -> {89 83} [style=dotted];
83 -> {84} [style=dotted];
84 -> {85} [style=dotted];
85 -> {86} [style=dotted];
86 -> {87} [style=dotted];
87 -> {88} [style=dotted];
88 -> {89} [style=dotted];
89 -> {61} [color=green style=dotted];
88 -> {60} [color=green style=dotted];
89 -> {90};
90 -> {91};
91 -> {92};
92 -> {93 98};
93 -> {94};
94 -> {101};
91 -> {92 97};
92 -> {93};
93 -> {100};
93 -> {95} [color=red];
93 -> {100} [style=dashed];
94 -> {96} [color=red];
94 -> {101} [style=dashed];
95 -> {97} [color=red];
96 -> {97} [color=green];
95 -> {96} [color=green];
96 -> {97};
97 -> {98};
98 -> {99};
99 -> {100};
100 -> {101};
101 -> {102};
102 -> {103};
103 -> {104};
104 -> {105};
105 -> {106};
106 -> {95} [color=red];
106 -> {96} [color=green];
105 -> {94} [color=red];
105 -> {95} [color=green];
}

View File

@@ -9,9 +9,9 @@ abstract class My<T : Some> {
abstract fun foo(arg: T)
abstract val y: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>My<!>.T
abstract val y: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>My.T<!>
abstract val z: test.<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>My<!>.T
abstract val z: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>test.My.T<!>
class Some : <!SUPERTYPE_NOT_A_CLASS_OR_INTERFACE, UNRESOLVED_REFERENCE!>T<!>()
}

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